SQL COMMAND · 类型与运算符
CREATE DOMAIN
定义一个新域
CREATE类型与运算符引入 10(基线)现存至 20 devel2 次语法变更
- 动词
CREATE- 对象
DOMAIN- 分组
- 类型与运算符
- 引入版本
- 10(基线)
- 状态
- 现存
- 语法变更次数
- 2
- 手册小节数
- 6
版本轨迹
相对 PostgreSQL 17 无变化。
语法铁道图 PostgreSQL 18
沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。
domain_constraint
语法概要
CREATE DOMAINname[ AS ]data_type[ COLLATEcollation] [ DEFAULTexpression] [domain_constraint[ ... ] ] 其中domain_constraint是: [ CONSTRAINTconstraint_name] { NOT NULL | NULL | CHECK (expression) }
描述
CREATE DOMAIN创建一个新域。域本质上是一种带有可选 约束(即对允许值集合的限制)的数据类型。定义域的用户将成为其拥有者。
如果给定了模式名(例如CREATE DOMAIN myschema.mydomain ...),则该域会在指定模式中创建。否则它会 在当前模式中创建。域名在其所在模式中的现有类型和域之间必须唯一。
域适合把字段上的常见约束抽象到单一位置进行维护。例如,若有多个表都 包含电子邮件地址列,并且都需要同一个 CHECK 约束来验证地址语法, 那么定义一个域会比在每个表上分别设置该约束更合适。
要创建域,你必须对其底层类型拥有USAGE权限。
参数
name要创建的域名(可选地带模式限定)。
data_type该域的底层数据类型。它可以包含数组说明符。
collation该域的可选排序规则。如果未指定排序规则,则该域的排序规则行为与其 底层数据类型相同。如果指定了
COLLATE,则底层 类型必须是一种可排序数据类型。DEFAULTexpressionDEFAULT子句为该域数据类型的列指定默认值。 该值可以是任意不含变量的表达式(但不允许子查询)。默认表达式的 数据类型必须与该域的数据类型匹配。如果未指定默认值,则默认值为 空值。默认表达式会在任何未为该列指定值的插入操作中使用。如果为某个 特定列定义了默认值,它就会覆盖与该域关联的任何默认值。反过来, 域默认值又会覆盖与底层数据类型关联的任何默认值。
CONSTRAINTconstraint_name约束的可选名称。如果未指定,系统会生成一个名称。
NOT NULL该域的值不允许为空值(但见下文注解)。
NULL该域的值允许为空值。这是默认行为。
该子句仅用于与非标准 SQL 数据库兼容。不鼓励在新应用中使用它。
CHECK (expression)CHECK子句指定该域的值必须满足的完整性 约束或测试。每个约束都必须是一个产生布尔结果的表达式。它应使用 关键字VALUE来引用被测试的值。求值结果为 TRUE 或 UNKNOWN 的表达式会通过检查。如果表达式产生 FALSE 结果,就会 报告错误,并且不允许将该值转换成该域类型。当前,
CHECK表达式不能包含子查询,也不能引用VALUE之外的其他变量。当一个域有多个
CHECK约束时,会按名称的字母顺序 测试它们。(9.5 之前的PostgreSQL版本 并不保证CHECK约束遵循任何特定的触发顺序。)
注解
域约束,特别是NOT NULL,会在把值转换成域类型时 进行检查。即便存在这样的约束,一个名义上属于该域类型的列也仍可能 读出为空值。例如,在外连接查询中,如果该域列位于外连接中可为空的 一侧,就可能发生这种情况。一个更微妙的例子是:
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
这个空标量子 SELECT 会产生一个空值,该空值被视为域类型的值,因此 不会再对其执行进一步的约束检查,插入也会成功。
由于 SQL 普遍假定空值是每种数据类型的合法值,因此很难彻底避免这类 问题。因此,最佳实践是把域约束设计为允许空值,然后在需要时对该域 类型的列应用列级NOT NULL约束,而不是直接对域 类型应用这种约束。
PostgreSQL假定CHECK 约束的条件是不可变的,也就是说,对于相同的输入值,它们总会给出相同 的结果。正是基于这一假设,系统只会在值首次被转换为域类型时检查 CHECK约束,而不会在其他时候检查。(这与表 CHECK约束的处理方式基本相同,如Section 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)。 不过,正如the section called “注解”所述,这类约束在 实践中最好还是避免使用。)NULL“约束” 也是PostgreSQL扩展(另见Compatibility)。
另见
语法演化
相邻大版本之间的差异,新的在前。版本号链接到对应快照。
PostgreSQL 14← 13语法变化
+ [ domain_constraint [ ... ] ]+ 其中 domain_constraint 是:− [ constraint [ ... ] ]− 其中constraint为:正文更新PostgreSQL 12← 11正文更新
正文更新PostgreSQL 11← 10语法变化
+ 其中constraint为:− 其中 constraint 为:正文更新
同组命令
| 命令 | 动词 | 对象 | 版本变动 | 最近变更 |
|---|---|---|---|---|
CREATE CAST | CREATE | CAST | — | |
| 定义一种新的类型转换 | 现存 | |||
DROP CAST | DROP | CAST | — | |
| 移除一个类型转换 | 现存 | |||
CREATE COLLATION | CREATE | COLLATION | 142 次 | |
| 定义一种新排序规则 | 现存 | |||
ALTER COLLATION | ALTER | COLLATION | 141 次 | |
| 更改排序规则的定义 | 现存 | |||
DROP COLLATION | DROP | COLLATION | — | |
| 删除一个排序规则 | 现存 | |||
CREATE CONVERSION | CREATE | CONVERSION | — | |
| 定义一个新的编码转换 | 现存 | |||
ALTER CONVERSION | ALTER | CONVERSION | 141 次 | |
| 更改一个转换的定义 | 现存 | |||
DROP CONVERSION | DROP | CONVERSION | — | |
| 移除一个转换 | 现存 | |||
CREATE DOMAIN | CREATE | DOMAIN | 142 次 | |
| 定义一个新域 | 现存 | |||
ALTER DOMAIN | ALTER | DOMAIN | 142 次 | |
| 更改一个域的定义 | 现存 | |||
DROP DOMAIN | DROP | DOMAIN | — | |
| 移除一个域 | 现存 | |||
CREATE OPERATOR | CREATE | OPERATOR | 192 次 | |
| 定义一个新的操作符 | 现存 | |||
ALTER OPERATOR | ALTER | OPERATOR | 141 次 | |
| 更改一个操作符的定义 | 现存 | |||
DROP OPERATOR | DROP | OPERATOR | 141 次 | |
| 移除一个操作符 | 现存 | |||
CREATE OPERATOR CLASS | CREATE | OPERATOR CLASS | — | |
| 定义一个新的操作符类 | 现存 | |||
ALTER OPERATOR CLASS | ALTER | OPERATOR CLASS | 141 次 | |
| 更改一个操作符类的定义 | 现存 | |||
DROP OPERATOR CLASS | DROP | OPERATOR CLASS | — | |
| 移除一个操作符类 | 现存 | |||
CREATE OPERATOR FAMILY | CREATE | OPERATOR FAMILY | — | |
| 定义一个新的操作符族 | 现存 | |||
ALTER OPERATOR FAMILY | ALTER | OPERATOR FAMILY | 141 次 | |
| 更改一个操作符族的定义 | 现存 | |||
DROP OPERATOR FAMILY | DROP | OPERATOR FAMILY | — | |
| 移除一个操作符族 | 现存 | |||
CREATE TYPE | CREATE | TYPE | 141 次 | |
| 定义一种新的数据类型 | 现存 | |||
ALTER TYPE | ALTER | TYPE | 142 次 | |
| 更改类型的定义 | 现存 | |||
DROP TYPE | DROP | TYPE | — | |
| 移除一个数据类型 | 现存 | |||