Lin*_*nk0 13 postgresql composite-types domain
假设我想要一个复合类型的地址,例如:
create type address as (
city text,
address_line text,
zip_code int
);
Run Code Online (Sandbox Code Playgroud)
为了使数据完整性更好,我不想允许NULL
s 成为city
、address_line
或 的成员zip_code
。所以我想对not null
这些字段进行限制。
创建域检查对我来说不起作用。所以这段代码会产生错误:
create domain address_domain as address
check (
value.city is not null and
value.address_line is not null and
value.zip_code is not null
);
Run Code Online (Sandbox Code Playgroud)
您可能会说:“那么,为什么不将地址存储为三列,并向字段添加约束呢?”。我会回答说,我希望能够使地址本身可以为空,但如果地址存在,那么它的所有字段也应该存在。像这样的东西:
create table companies (
id serial primary key,
name text not null,
headquaters address -- this one can be null tho
)
Run Code Online (Sandbox Code Playgroud)
Mel*_*kij 12
复合类型检查约束的正确语法如下所示:
create domain address_domain as address
check (
(value).city is not null and
(value).address_line is not null and
(value).zip_code is not null
);
Run Code Online (Sandbox Code Playgroud)
让我们检查:
melkij=> create table test_address_domain (a address_domain);
CREATE TABLE
melkij=> insert into test_address_domain values (('foo', 'bar', 11));
INSERT 0 1
melkij=> insert into test_address_domain values (('foo', 'bar', null)); -- fails
ERROR: value for domain address_domain violates check constraint "address_domain_check"
melkij=> insert into test_address_domain values (('foo', null, 11)); -- fails
ERROR: value for domain address_domain violates check constraint "address_domain_check"
melkij=> insert into test_address_domain values ((null, 'bar', 11)); -- fails
ERROR: value for domain address_domain violates check constraint "address_domain_check"
melkij=> insert into test_address_domain values (null); -- fails
ERROR: value for domain address_domain violates check constraint "address_domain_check"
Run Code Online (Sandbox Code Playgroud)
但请注意最后一行。看来这不是你想要的。尝试明确允许:
melkij=*> create domain address_domain2 as address
check (
value is null or (
(value).city is not null and
(value).address_line is not null and
(value).zip_code is not null
));
CREATE DOMAIN
melkij=*> create table test_address_domain2 (a address_domain2);
CREATE TABLE
melkij=*> insert into test_address_domain2 values (null); -- works now
INSERT 0 1
Run Code Online (Sandbox Code Playgroud)