admin

如何强制多个唯一集(列组合)在SQLite中互斥?

sql

考虑一个包含可空列abc,def和xyz的表。如何执行:

  1. 如果’abc’不为null,则将1(’abc’)设置为UNIQUE,并且
  2. 如果’def’和’xyz’都不为null,则将2(’def,xyz’)设置为UNIQUE,并且
  3. 上述集合中只有一个有效(包含非null)。

这是我尝试过的代码:

--# sqlite3 --version
--  3.13.0 ....

DROP TABLE IF EXISTS try;
CREATE TABLE try(
    -- 'abc' should be null,                  when 'def' and 'xyz' are not null.
    -- 'abc' should be not be null,           when 'def' and 'xyz' are null.
    -- 'def' and 'xyz' should be null,        when 'abc' is not null.
    -- 'def' and 'xyz' should be not be null, when 'abc' is null.

    abc  TEXT,
    def  TEXT,
    xyz  TEXT,
    CONSTRAINT combo_1 UNIQUE(abc),
    CONSTRAINT combo_2 UNIQUE(def, xyz)
);

INSERT into try(abc)            VALUES("a1");              -- should succeed
INSERT into try(def, xyz)       VALUES("d2", "x2");        -- should succeed
--
INSERT into try(abc)            VALUES(null);              -- should not be allowed
INSERT into try(abc, def)       VALUES("a4", "d4");        -- should not be allowed
INSERT into try(abc, xyz)       VALUES("a5", "x5");        -- should not be allowed
INSERT into try(abc, def, xyz)  VALUES("a6", "d6", "x6");  -- should not be allowed
--
INSERT into try(def)            VALUES(null);              -- should not be allowed
INSERT into try(def)            VALUES("d8");              -- should not be allowed
--
INSERT into try(xyz)            VALUES(null);              -- should not be allowed
INSERT into try(xyz)            VALUES("x10");             -- should not be allowed
--
INSERT into try(def, xyz)       VALUES(null, null);        -- should not be allowed
INSERT into try(def, xyz)       VALUES("d12", null);       -- should not be allowed
INSERT into try(def, xyz)       VALUES(null, "x13");       -- should not be allowed

INSERT into try(abc, def, xyz)  VALUES(null, null, null);  -- should not be allowed

.headers ON
select rowid,* from try;

.echo on
--
-- Only these 2 rows should be present:
-- 1|a1||
-- 2||d2|x2
--

但是,当我只希望前两个成功时,所有14个插入都成功。


阅读 158

收藏
2021-07-01

共1个答案

admin

换句话说:对空,两者均abcdef列应该是不同的,而在中defxyz列应该是相同的。

这可以通过两个附加的表约束来完成:

CHECK((abc IS NULL) <> (def IS NULL)),
CHECK((def IS NULL) =  (xyz IS NULL))
2021-07-01