是否可以进行XOR CHECK CONSTRAINT?
我在一个我刚做的测试表上做,这个表叫做test,有3列:
- id,bigint
- a,bigint
- B,bigint
我为此做了一个检查约束:
(a IS NOT NULL AND b = NULL) OR (b IS NOT NULL AND a = NULL)
Which apparently would work in MSSQL
我通过这样做来测试它:
INSERT INTO public.test(
id, a, b)
VALUES (1, 1, 1);
这应该失败,因为它在OR的任何一侧都没有计算为TRUE。不过,插得很好。
当我查看postgres实际存储的约束时,我得到了这个:
(a IS NOT NULL AND b = NULL::bigint OR b IS NOT NULL AND a = NULL::bigint)
我听说AND优先于OR,所以即使这样也应该有效。
有没有人对此有一个解决方案?优选地,也可以具有三个或更多个柱的一个?我知道这些可能会更复杂。
编辑:改变
= NULL
到
IS NULL
给予我:
ERROR: cannot cast type boolean to bigint
5条答案
按热度按时间8xiog9wr1#
右,
a = NULL
和b = NULL
位是@a_horse_with_no_name的问题。你也可以考虑这个导数,它不需要OR
运算符:当然,这只适用于两列
XOR
比较。在类似的测试表中使用三列或更多列XOR
比较,您可以采用类似的方法,更像这样:jvlzgdj92#
你不能用
=
比较NULL值,你需要IS NULL
对于check约束,需要将整个表达式括在括号中:
或者,check约束可以简化为
这也更容易调整到更多的列
gjmwrych3#
这是明确的异或。为什么不先把它定义为布尔运算符呢?它可能对其他情况也有用。
然后检查
((a IS NULL) # (b IS NULL))
wqsoz72f4#
感谢维克。我有一个类似的测试在一个视图。在左联接中,至少有2列或更多列不能为空。
6mzjoqzu5#
类似于前面使用a_horse_with_no_name表示的
num_nonnulls(a, b, c, ...) = 1
,您也可以使用具有任意列数的数组。示例:
逻辑:
1.将所有列值放入数组中
1.从该数组中删除所有NULL
1.检查是否只剩下一个值。
在Postgres 11上测试。