【问题标题】:Conditional Not Null Constraint条件非空约束
【发布时间】:2020-06-15 10:14:40
【问题描述】:

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

我有两列:

  • oncost (boolean)
  • oncostdescription (varchar)

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

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

编辑:
我忘了说明我的 postgres 版本低于 12。
这里的一些人想出了一个很酷的功能,叫做generated columns
看起来很酷。但前提是你有 12+

【问题讨论】:

  • 可能删除oncost,因为它是多余的?
  • 我会考虑一个拒绝“空”值的检查约束。
  • 请不要在您的问题中添加解决方案。它已经在答案中了。

标签: sql postgresql create-table check-constraints


【解决方案1】:

您可以使用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 = '')
        )
    )
)

【讨论】:

  • 谢谢。你的第一个建议就成功了!不错!
【解决方案2】:

如果我理解正确,生成的列可能会做你想做的事:

create table t (
     . . . 
     oncostdescription varchar,
     oncost boolean generated always as (oncostdescription is not null)
);

这假设您希望 oncost 作为一个布尔标志,指示 oncostdescription 是否具有值 - 这与问题的措辞一致。

【讨论】:

  • 谢谢,但我忘了说明我的 postgres 版本低于 12。此功能 generated 显然仅适用于版本 +12 - 请参阅此处 pgdash.io/blog/postgres-12-generated-columns.html
  • @ThomasLang 。 . .那么,也许一个观点就足够了。如果您只想要一个标志,我不建议您实际存储该值。
【解决方案3】:

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;

【讨论】:

    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 2015-08-23
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多