CREATE DOMAIN
Posted 丹心明月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CREATE DOMAIN相关的知识,希望对你有一定的参考价值。
CREATE DOMAIN:定义新域。
语法:
CREATE DOMAIN name [ AS ] data_type
[ COLLATE collation ]
[ DEFAULT expression ]
[ constraint [ ... ] ]
where constraint is:
[ CONSTRAINT constraint_name ]
NOT NULL | NULL | CHECK (expression)
描述:
CREATE DOMAIN创建一个新的域。域本质上是一种可带约束(对允许值子集的限制)的数据类型。域定义者为域的所有者。
如果在创建域时指定了模式(CREATE DOMAIN myschema.mydomain...),则该域在该模式下创建。否则,域创建在当前模式下。域名不可与已有类型及域名重名。
域对于将字段上的公共约束抽象到单个位置进行维护非常有用。例如,可能好几个表都有email地址列,均需要使用CHECK约束检查邮件地址。此时可创建一个域进行管理,而无需对每个表都创建检查约束。
若要创建域,则需要对底层类型有USAGE权限。
参数:
name
域名。
data_type
域所使用的底层数据类型。可包含数组说明符。
collation
域的可选排序规则。若未指定,则使用底层数据类型默认排序规则。如果需要COLLATE选项,那么底层数据必须可排序。
DEFAULT expression
DEAFULT子句为域数据类型列指定默认值。可使用变量,但不可使用子查询。若未指定默认值,则默认值为空。在insert语句未对列指定值时,使用默认表达式。若为特定列指定了默认值,则覆写域默认值。域默认值会覆写底层数据类型的默认值。
CONSTRAINT constraint_name
约束名。若未指定,则系统自动生成。
NOT NULL
限定值非空。
NULL
限定值可以为空,此为默认行为。
CHECK(expression)
检查约束指定完整约束或域值需满足的条件。表达式需返回布尔值。需要使用关键字VALUE来制定需要测试的值。返回TRUE或UNKNOWN的值插入成功,否则失败。
当前检查约束不可指定子查询,也不可指定除VALUE之外的变量。如果存在多个检查约束,则根据约束名称排序依次验证。
注意事项:
域约束,特别是NOT NULL约束,是在将值转换到域类型时进行检查。故即使定义了非空,域列读取时也可能为空。例如,这可能在外连接查询中发生:域列在外连接的可为空的一边。
一个较为微妙的例子:
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
空的标量子查询会产生一个被认为是域类型的空值,故不会进一步进行约束检查,所以该插入语句会成功。
因为空值被认为可以是任意类型,所以很难规避此类问题。故最佳实践是首先定义一个允许空值的域类型,然后在域类型的列上定义非空约束,而非直接在域上定义非空。
PostgreSQL假定检查约束条件为固定的,即对于同一输入必为相同输出。而打破此假设的一个场景是:在检查约束中引用用户自定的函数,而后期又更改了函数定义。PostgreSQL虽然不禁止这样做,但为避免造成混淆,建议修改引用函数的最佳实践是:首先删掉该检查约束;然后修改引用的函数定义;最后再重新创建该检查约束。
示例:
该示例创建 us_postal_code数据类型,然后创建使用该类型的表:
CREATE DOMAIN us_postal_code AS TEXT
CHECK(
VALUE ~ '^\\d5$'
OR VALUE ~ '^\\d5-\\d4$'
);
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标准。
参见:
以上是关于CREATE DOMAIN的主要内容,如果未能解决你的问题,请参考以下文章
[reproduce]How to Create Domain in Windows Server 2012.
Laravel:错误 InvalidArgumentException
Python RuntimeWarning:长标量中遇到溢出