2024年9月26日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3

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));

空标量子 SELECT 将产生一个 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 扩展(另请参阅 兼容性)。

另请参阅

ALTER DOMAINDROP DOMAIN

提交更正

如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表单 报告文档问题。