具有空值的 sqlite3 复合唯一约束

时间:2021-07-01 19:18:05

标签: sql sqlite unique-constraint

如何设置可以正确处理sqlite中的空值的复合唯一约束?这可能通过示例更好地表达:

CREATE TABLE people (
    id INTEGER PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    suffix TEXT,
    UNIQUE (first_name, last_name, suffix)
);

当一个人的后缀被输入不止一次时,约束会按预期工作。

-- Last insert is denied
INSERT INTO people (first_name, last_name, suffix)
VALUES
    ('Joe', 'Dirt', 'Sr'),
    ('Joe', 'Dirt', 'Jr'),
    ('Joe', 'Dirt', 'Sr');

但是,当没有后缀的人被多次插入时,唯一约束不适用。

-- Both are permitted
INSERT INTO people (first_name, last_name)
VALUES
    ('Chris', 'Farley'),
    ('Chris', 'Farley');

我知道 sqlite 将空值视为相互独立的,但是有没有合适的方法来解决这个问题?

任何帮助将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:1)

只有当后缀为空时,您才能为 first_namelast_name 创建唯一的 partial index

CREATE UNIQUE INDEX idx_people ON people(first_name, last_name) 
WHERE suffix IS NULL;

查看简化的 demo

如果您的 SQLite 版本是 3.31.0+,您可以创建一个生成的列,当 suffixnull 时返回一个空字符串,并在唯一约束中使用它而不是 {{1} }:

suffix

答案 1 :(得分:1)

后缀为空字符串默认设置为非空。这可能会解决您的问题(NULL 与 '' 不同,NULL 是我不知道的,所以在下面的代码中,您说中间名是空字符串,而不是 NULL)。

CREATE TABLE people (
    id INTEGER PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    suffix TEXT DEFAULT '' NOT NULL,
    UNIQUE (first_name, last_name, suffix)
);