CREATE DOMAIN — 定义一个新域
CREATE DOMAINname[ AS ]data_type[ COLLATEcollation] [ DEFAULTexpression] [domain_constraint[ ... ] ] wheredomain_constraintis: [ CONSTRAINTconstraint_name] { NOT NULL | NULL | CHECK (expression) }
CREATE DOMAIN 创建一个新域。域本质上是一种数据类型,带有可选的约束(对允许的值集进行限制)。定义域的用户成为其所有者。
如果给出了模式名(例如,CREATE DOMAIN myschema.mydomain ...),则该域将在指定的模式中创建。否则,它将在当前模式中创建。域的名称在其模式中存在的类型和域之间必须是唯一的。
域可用于将字段的常见约束抽象到一个位置进行维护。例如,多个表可能包含电子邮件地址列,所有这些列都需要相同的 CHECK 约束来验证地址语法。应定义一个域,而不是单独设置每个表的约束。
要能够创建域,您必须拥有底层类型上的 USAGE 权限。
name要创建的域的名称(可选模式限定)。
data_type域的底层数据类型。这可以包括数组说明符。
collation域的可选排序规则。如果未指定排序规则,则域具有与其底层数据类型相同的排序规则行为。如果指定了 COLLATE,则底层类型必须是可排序的。
DEFAULT expressionDEFAULT 子句为域数据类型列指定默认值。值是任何不含变量的表达式(但不能使用子查询)。默认表达式的数据类型必须与域的数据类型匹配。如果未指定默认值,则默认值为 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 的扩展(另请参见 兼容性)。
如果您在文档中发现任何不正确、与您的特定功能体验不符或需要进一步澄清的内容,请使用 此表单报告文档问题。