Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

CREATE DOMAIN

CREATE DOMAIN — 定义一个新的域

概要

CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ domain_constraint [ ... ] ]

where domain_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | CHECK (expression) }

描述

CREATE DOMAIN 创建一个新域。一个域本质上是一个具有可选约束(对所允许的值集的限制)的数据类型。定义域的用户将成为其所有者。

如果给出了模式名称(例如,CREATE DOMAIN myschema.mydomain ...),则在指定模式中创建域。否则,它将在当前模式中创建。域名称在模式中的类型和域中必须唯一。

域可用于将字段的公用约束抽象到一个位置以进行维护。例如,多个表可能包含电子邮件地址列,全部需要相同的 CHECK 约束以验证地址语法。定义一个域,而不单独设置每个表的约束。

要能够创建域,您必须对基础类型拥有 USAGE 权限。

参数

name

要创建的域的名称(可选的模式限定)。

data_type

域的基础数据类型。这可以包括数组说明符。

collation

域的可选校对。如果未指定校对,则域与基础数据类型具有相同的校对行为。如果指定 COLLATE,则基础类型必须可以校对。

DEFAULT expression

DEFAULT 子句为域数据类型的列指定默认值。该值是任何无变量表达式(但不允许子查询)。默认表达式的类型必须与域的数据类型匹配。如果未指定默认值,则默认值将为 null 值。

在任何未为该列指定值的插入操作中,都将使用默认表达式。如果已为特定列定义了默认值,则它将覆盖与域关联的任何默认值。反过来,域默认值将覆盖与基础数据类型关联的任何默认值。

CONSTRAINT constraint_name

约束的可选名称。如果未指定,系统将生成一个名称。

NOT NULL

禁止此域的值为 null(但请见以下注释)。

NULL

允许此域的值为 null。这是默认值。

此子句仅适用于与非标准 SQL 数据库的兼容性。不鼓励在新应用程序中使用它。

CHECK (expression)

CHECK 子句指定完整性约束或域值必须满足的测试。每个约束必须是生成布尔结果的表达式。它应使用关键字 VALUE 引用正在测试的值。计算结果为 TRUE 或 UNKNOWN 的表达式会成功。如果表达式生成 FALSE 结果,则会报告错误并且不允许该值转换为域类型。

当前,CHECK 表达式不能包含子查询也不引用 VALUE 以外的变量。

当一个域有多个 CHECK 约束时,它们将按名称进行按字母顺序列出进行测试。(PostgreSQL 9.5 版本之前的并不支持 CHECK 约束的特定触发顺序。)

说明

域约束,特别是 NOT NULL,在将值转换为域类型时进行检查。名义上为域类型的一列可能会读为 null,尽管存在此类约束。例如,如果域列位于外联接的可空一侧,则可能会在外联接查询中发生这种情况。更微妙的例子是

INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));

空标量子查询将生成被视为域类型的一个 null 值,所以对其不应用进一步的约束检查,而且插入操作会成功。

由于 SQL 通常会假定 null 值为每个数据类型的合法值,因此很难避免此类问题。因此,最佳实践是设计域的约束,以便允许 null 值,然后根据需要将列 NOT NULL 约束应用于域类型的列,而不是直接应用于域类型。

PostgreSQL 假设 CHECK 约束的条件是不可变的,也就是说,它们将始终针对同一输入值产生相同的结果。此假设证明了只有在值首次转换为域类型时才检查 CHECK 约束,而不在其他时间进行的原因。(这实际上与 第 5.5.1 节 中所述的表 CHECK 约束的处理方式相同。)

破坏此假设的一种常见方法的示例是在 CHECK 表达式中引用用户定义的函数,然后更改该函数的行为。PostgreSQL 并未禁止这样做,但如果存在现在违反 CHECK 约束的存储的域类型值,它不会注意到这一点。这将导致后续数据库转储和还原操作失败。处理此类更改的建议方法是删除该约束(使用 ALTER DOMAIN),调整函数定义并重新添加约束,从而针对存储的数据重新对其进行检查。

同样,最好确保域 CHECK 表达式不会引发错误。

示例

此示例创建 us_postal_code 数据类型,然后再在表定义中使用该类型。正则表达式测试用于验证值是否像有效的美国邮政编码

CREATE DOMAIN us_postal_code AS TEXT
CHECK(
   VALUE ~ '^\d{5}$'
OR VALUE ~ '^\d{5}-\d{4}$'
);

CREATE TABLE us_snail_addy (
  address_id SERIAL PRIMARY KEY,
  street1 TEXT NOT NULL,
  street2 TEXT,
  street3 TEXT,
  city TEXT NOT NULL,
  postal us_postal_code NOT NULL
);

兼容性

命令 CREATE DOMAIN 符合 SQL 标准。

此命令中的语法 NOT NULL 是一个 PostgreSQL 扩展。(可以用 CHECK (VALUE IS NOT NULL) 来编写相同内容,这是符合标准的方式。但根据 “备注”部分 中的内容,最好在实践中尽量避免此类约束。)NULL 约束PostgreSQL 扩展(另请参见 兼容性)。

另请参见

ALTER 域DROP 域