Postgresql 中文操作指南
Synopsis
CREATE DOMAIN name [ AS ] data_type
[ COLLATE collation ]
[ DEFAULT expression ]
[ constraint [ ... ] ]
where constraint is:
[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | CHECK (expression) }
Description
CREATE DOMAIN 创建一个新域。域本质上是一种数据类型,具有可选约束(对一系列允许值的限制)。定义域的用户将成为其所有者。
如果给定了架构名称 (例如 CREATE DOMAIN myschema.mydomain … ),则该域将在指定的架构中创建。否则,将在当前架构中创建。域名称在其架构中现有的类型和域中必须是唯一的。
域对于将对字段的通用约束抽象到一个位置以进行维护非常有用。例如,几个表可能包含电子邮件地址列,都需要相同的 CHECK 约束来验证地址语法。定义域,而不是单独设置每个表的约束。
要创建域,你必须对基础类型具有 USAGE 权限。
Parameters
-
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 约束时,它们将按名称按字母顺序列出。(9.5 之前的 PostgreSQL 版本不会对 CHECK 约束满足任何特定的触发顺序。)
-
Notes
域约束(尤其是 NOT NULL )会在将值转换为域类型时得到检查。尽管存在此类约束,但名义上属于该域类型的列仍可能读为 null。例如,如果域列位于外连接的可空一侧,则这可能会在外连接查询中发生。一个更微妙的示例是
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
空的标量子选择将生成一个 null 值,该值被认为属于该域类型,因此不会对此值应用进一步的约束检查,并且插入操作将成功。
由于 SQL 通常假设 null 值是每种数据类型的有效值,因此很难避免此类问题。因此,最佳做法是设计该域的约束,以便允许 null 值,然后根据需要将列 NOT NULL 约束应用到该域类型的列,而不是直接应用到该域类型上。
PostgreSQL 假设 CHECK 约束的条件是不可变的,换句话说,它们将始终针对相同的输入值给出相同的结果。此假设论证了只能在首次将值转换为域类型时检查 CHECK 约束,而不能在其他时间进行检查。(这在本质上与表 CHECK 约束的处理相同,如 Section 5.4.1 中所述。)
以在 CHECK 表达式中引用用户定义函数,然后更改该函数的行为为例来打破此假设的做法很常见。PostgreSQL 不会禁止这样做,但如果没有违反 CHECK 约束的存储域类型值,它不会注意到。这会导致随后的数据库转储和还原失败。处理此类更改的建议方法是删除约束(使用 ALTER DOMAIN )、调整函数定义,然后重新添加约束,从而根据存储的数据重新对它进行检查。
确保域 CHECK 表达式不会引发错误也是一种良好做法。
Examples
此示例创建了 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
);