CREATE DOMAIN — 定义一个新的域
CREATE DOMAINname
[ AS ]data_type
[ COLLATEcollation
] [ DEFAULTexpression
] [domain_constraint
[ ... ] ] wheredomain_constraint
is: [ CONSTRAINTconstraint_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
约束,而不是在其他时间检查的合理性。(这本质上与表 CHECK
约束的处理方式相同,如 第 5.5.1 节所述。)
打破此假设的常见方法的一个示例是在 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 扩展(另请参阅 兼容性)。
如果您在文档中发现任何不正确的内容,与特定功能不符或需要进一步澄清的内容,请使用此表单报告文档问题。