条件非空约束

Conditional Not Null Constraint

有没有办法在 postgres SQL 中使用约束检查(或其他函数)对以下行为进行建模:

我有两列:

如果 oncost 是 true,我希望 oncostdescription 是强制性的(NOT NULLNOT EMPTY

如果 concost 是 false,我希望 oncostdescription 不是强制性的(NULLEMPTY

编辑:
我忘了说明我的 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;