条件非空约束
Conditional Not Null Constraint
有没有办法在 postgres SQL 中使用约束检查(或其他函数)对以下行为进行建模:
我有两列:
oncost (boolean)
oncostdescription (varchar)
如果 oncost 是 true
,我希望 oncostdescription
是强制性的(NOT NULL
,NOT EMPTY
)
如果 concost 是 false
,我希望 oncostdescription
不是强制性的(NULL
,EMPTY
)
编辑:
我忘了说明我的 postgres 版本低于 12。
这里的一些人想出了一个很酷的功能,叫做 generated columns
。
看起来很酷。但前提是你有 12+
您可以使用 check
约束:
create table mytable (
oncost boolean
oncostdescription varchar(50),
constraint ck_mytable check(
not oncost
or not (oncostdescription is null or oncostdescription = '')
)
)
这句话为:布尔标志为假,或者描述既不为空也不为空。
您也可以将其表示为:
create table mytable (
oncost boolean
oncostdescription varchar(50),
constraint ck_mytable check(
not (
oncost
and (oncostdescription is null or oncostdescription = '')
)
)
)
如果我理解正确,生成的列可能会执行您想要的操作:
create table t (
. . .
oncostdescription varchar,
oncost boolean generated always as (oncostdescription is not null)
);
这假设您希望 oncost
作为一个布尔标志,指示 oncostdescription
是否有一个值——这与问题的措辞方式一致。
oncost
列是多余的(完全依赖于 oncostdescription
),因此可以在需要时进行计算。 Postgres-12 支持 generated always as ...
列:
CREATE TABLE omg
( seq integer not null generated always as identity
, oncostdescription varchar
, oncost boolean NOT NULL generated always as ( oncostdescription IS NOT NULL AND oncostdescription > '') STORED
);
insert into omg(oncostdescription) VALUES ( NULL), (''), ('a'), (' ');
select * from omg;
结果:
CREATE TABLE
INSERT 0 4
seq | oncostdescription | oncost
-----+-------------------+--------
1 | | f
2 | | f
3 | a | t
4 | | t
(4 rows)
并且由于 oncost
字段是可计算的,它也可以打包在一个视图中:
(结果完全一样)
CREATE VIEW vomg AS
SELECT seq, oncostdescription
, ( oncostdescription IS NOT NULL AND oncostdescription > '')::boolean AS oncost
FROM omg
;
SELECT * FROM vomg;
有没有办法在 postgres SQL 中使用约束检查(或其他函数)对以下行为进行建模:
我有两列:
oncost (boolean)
oncostdescription (varchar)
如果 oncost 是 true
,我希望 oncostdescription
是强制性的(NOT NULL
,NOT EMPTY
)
如果 concost 是 false
,我希望 oncostdescription
不是强制性的(NULL
,EMPTY
)
编辑:
我忘了说明我的 postgres 版本低于 12。
这里的一些人想出了一个很酷的功能,叫做 generated columns
。
看起来很酷。但前提是你有 12+
您可以使用 check
约束:
create table mytable (
oncost boolean
oncostdescription varchar(50),
constraint ck_mytable check(
not oncost
or not (oncostdescription is null or oncostdescription = '')
)
)
这句话为:布尔标志为假,或者描述既不为空也不为空。
您也可以将其表示为:
create table mytable (
oncost boolean
oncostdescription varchar(50),
constraint ck_mytable check(
not (
oncost
and (oncostdescription is null or oncostdescription = '')
)
)
)
如果我理解正确,生成的列可能会执行您想要的操作:
create table t (
. . .
oncostdescription varchar,
oncost boolean generated always as (oncostdescription is not null)
);
这假设您希望 oncost
作为一个布尔标志,指示 oncostdescription
是否有一个值——这与问题的措辞方式一致。
oncost
列是多余的(完全依赖于 oncostdescription
),因此可以在需要时进行计算。 Postgres-12 支持 generated always as ...
列:
CREATE TABLE omg
( seq integer not null generated always as identity
, oncostdescription varchar
, oncost boolean NOT NULL generated always as ( oncostdescription IS NOT NULL AND oncostdescription > '') STORED
);
insert into omg(oncostdescription) VALUES ( NULL), (''), ('a'), (' ');
select * from omg;
结果:
CREATE TABLE
INSERT 0 4
seq | oncostdescription | oncost
-----+-------------------+--------
1 | | f
2 | | f
3 | a | t
4 | | t
(4 rows)
并且由于 oncost
字段是可计算的,它也可以打包在一个视图中:
(结果完全一样)
CREATE VIEW vomg AS
SELECT seq, oncostdescription
, ( oncostdescription IS NOT NULL AND oncostdescription > '')::boolean AS oncost
FROM omg
;
SELECT * FROM vomg;