【问题标题】:sqlite3 composite unique contraint with null values具有空值的 sqlite3 复合唯一约束
【发布时间】:2021-09-13 20:32:21
【问题描述】:

如何设置一个复合唯一约束,可以正确处理 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 将 null 值视为彼此独立,但有没有适当的方法来解决这个问题?

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

【问题讨论】:

    标签: sql sqlite unique-constraint


    【解决方案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 时返回一个空字符串,并在唯一约束中使用它而不是 suffix

    CREATE TABLE people (
        id INTEGER PRIMARY KEY,
        first_name TEXT NOT NULL,
        last_name TEXT NOT NULL,
        suffix TEXT,
        str_suffix GENERATED ALWAYS AS (COALESCE(suffix, '')),
        UNIQUE (first_name, last_name, str_suffix)
    );
    

    【讨论】:

      【解决方案2】:

      将后缀空字符串设为默认值,并将其设置为非空。这可能会解决您的问题(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)
      );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-14
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多