Bla*_*nen 7 sql postgresql constraints xor
是否可以制作XOR CHECK CONSTRAINT?
我是在我刚刚制作的测试表上做的,它叫做test并有3列:
我为此做了一个检查约束:
(a IS NOT NULL AND b = NULL) OR (b IS NOT NULL AND a = NULL)
Run Code Online (Sandbox Code Playgroud)
我通过这样做测试了它:
INSERT INTO public.test(
id, a, b)
VALUES (1, 1, 1);
Run Code Online (Sandbox Code Playgroud)
哪个应该失败,因为它在OR的任何一侧都没有评估为TRUE.但是,插入就好了.
当我看到postgres实际存储为约束时,我得到了这个:
(a IS NOT NULL AND b = NULL::bigint OR b IS NOT NULL AND a = NULL::bigint)
Run Code Online (Sandbox Code Playgroud)
我听说AND先于OR,所以即使这样也应该有效.
有人有解决方案吗?优选地,也可以具有三列或更多列?我知道那些可能会更复杂.
编辑:改变
= NULL
Run Code Online (Sandbox Code Playgroud)
至
IS NULL
Run Code Online (Sandbox Code Playgroud)
给我吗:
ERROR: cannot cast type boolean to bigint
Run Code Online (Sandbox Code Playgroud)
Vic*_*Vic 17
是的,a = NULL并且b = NULL位是@a_horse_with_no_name指示的问题.您也可以考虑这种衍生物,它不需要OR操作员:
create table test
(
id integer primary key,
a integer,
b integer,
check ((a IS NULL) != (b IS NULL))
);
Run Code Online (Sandbox Code Playgroud)
当然,这仅适用于两列XOR比较.XOR在类似的测试表中进行三次或更多列比较,您可以采用类似的方法:
create table test
(
id integer primary key,
a integer,
b integer,
c integer,
check ((a IS NULL)::INTEGER +
(b IS NULL)::INTEGER +
(c IS NULL)::INTEGER = 1)
);
Run Code Online (Sandbox Code Playgroud)
你不能比较NULL值=,你需要IS NULL
(a IS NOT NULL AND b is NULL) OR (b IS NOT NULL AND a is NULL)
Run Code Online (Sandbox Code Playgroud)
对于检查约束,您需要将整个表达式括在括号中:
create table xor_test
(
id integer primary key,
a integer,
b integer,
check ((a IS NOT NULL AND b is NULL) OR (b IS NOT NULL AND a is NULL))
);
-- works
INSERT INTO xor_test(id, a, b) VALUES (1, null, 1);
-- works
INSERT INTO xor_test(id, a, b) VALUES (2, 1, null);
-- failse
INSERT INTO xor_test(id, a, b) VALUES (3, 1, 1);
Run Code Online (Sandbox Code Playgroud)
这是明确的异或。为什么不先将其定义为布尔运算符呢?它对于其他情况也可能有用。
CREATE OR REPLACE FUNCTION public.xor (a boolean, b boolean) returns boolean immutable language sql AS
$$
SELECT (a and not b) or (b and not a);
$$;
CREATE OPERATOR #
(
PROCEDURE = public.xor,
LEFTARG = boolean,
RIGHTARG = boolean
);
Run Code Online (Sandbox Code Playgroud)
然后检查((a IS NULL) # (b IS NULL))
| 归档时间: |
|
| 查看次数: |
8445 次 |
| 最近记录: |