Postgresql 中文操作指南

CREATE DOMAIN

CREATE DOMAIN — 定义新域

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

Compatibility

CREATE DOMAIN 命令符合 SQL 标准。