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)
。然而,根据 “Notes”部分,实际上最好避免此类约束。) NULL
“约束”是 PostgreSQL 的扩展(另请参见 兼容性)。
如果您在文档中发现任何不正确、与您的特定功能体验不符或需要进一步澄清的内容,请使用 此表单报告文档问题。