强制使用多个列的唯一性可能为空
Enforce uniqueness with multiple columns possibly null
如果我有一个table,我想在 INSERT(使用 postgres)期间基于多个可以为空的列强制执行唯一性,我是否需要创建多个唯一索引,如下所示?
CREATE TABLE IF NOT EXISTS table_a (
id SERIAL PRIMARY KEY,
table_b_id INT REFERENCES table_b(id) ON DELETE CASCADE,
column_a INT,
column_b INT,
column_c INT,
created_time BIGINT NOT NULL,
CONSTRAINT "table_a_key" UNIQUE ("table_b_id", "column_a", "column_b", "column_c")
);
column_a
、column_b
和 column_c
都可以为空。对于 table.
,我只想要每条记录的这些列的唯一组合
有效插入
table_b_id | column_a | column_b | column_c
1 | 1 | 2 | 3
1 | 1 | null | null
1 | null | 2 | 3
1 | null | 2 | null
但是,如果我再次尝试插入1 | null | 2 | null
,就会发生冲突,无法插入。
考虑仅添加 CONSTRAINT "table_a_key" UNIQUE...
仅在所有列都没有任何空值时才强制执行唯一性。
我是否需要创建所有这些索引以确保唯一性?有没有更好的方法?
CREATE UNIQUE INDEX table_all_null_index ON table_a (table_b_id)
WHERE column_a IS NULL AND column_b IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_a_index ON table_a (table_b_id, column_a)
WHERE column_a IS NOT NULL AND column_b IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_b_index ON table_a (table_b_id, column_b)
WHERE column_b IS NOT NULL AND column_a IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_c_index ON table_a (table_b_id, column_c)
WHERE column_c IS NOT NULL AND column_a IS NULL AND column_b IS NULL;
CREATE UNIQUE INDEX table_a_col_a_b_index ON table_a (table_b_id, column_a, column_b)
WHERE column_a IS NOT NULL AND column_b IS NOT NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_a_c_index ON table_a (table_b_id, column_a, column_c)
WHERE column_a IS NOT NULL AND column_c IS NOT NULL AND column_b IS NULL;
CREATE UNIQUE INDEX table_a_col_b_c_index ON table_a (table_b_id, column_b, column_c)
WHERE column_b IS NOT NULL AND column_c IS NOT NULL AND column_a IS NULL;
如果您想允许多个 NULL
列,那么这就是常规唯一索引或约束的作用:
unique (a, b, c)
如果不希望NULL
的值重复,那么最简单的方法就是将它们默认为一个共同的值,例如-1
:
unique (coalesce(a, -1), coalesce(b, -1), coalesce(c, -1))
这可能并非在所有情况下都有效,但在许多情况下都有效,因为 -1
(或其他一些值)未以其他方式使用。
如果我有一个table,我想在 INSERT(使用 postgres)期间基于多个可以为空的列强制执行唯一性,我是否需要创建多个唯一索引,如下所示?
CREATE TABLE IF NOT EXISTS table_a (
id SERIAL PRIMARY KEY,
table_b_id INT REFERENCES table_b(id) ON DELETE CASCADE,
column_a INT,
column_b INT,
column_c INT,
created_time BIGINT NOT NULL,
CONSTRAINT "table_a_key" UNIQUE ("table_b_id", "column_a", "column_b", "column_c")
);
column_a
、column_b
和 column_c
都可以为空。对于 table.
有效插入
table_b_id | column_a | column_b | column_c
1 | 1 | 2 | 3
1 | 1 | null | null
1 | null | 2 | 3
1 | null | 2 | null
但是,如果我再次尝试插入1 | null | 2 | null
,就会发生冲突,无法插入。
考虑仅添加 CONSTRAINT "table_a_key" UNIQUE...
仅在所有列都没有任何空值时才强制执行唯一性。
我是否需要创建所有这些索引以确保唯一性?有没有更好的方法?
CREATE UNIQUE INDEX table_all_null_index ON table_a (table_b_id)
WHERE column_a IS NULL AND column_b IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_a_index ON table_a (table_b_id, column_a)
WHERE column_a IS NOT NULL AND column_b IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_b_index ON table_a (table_b_id, column_b)
WHERE column_b IS NOT NULL AND column_a IS NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_c_index ON table_a (table_b_id, column_c)
WHERE column_c IS NOT NULL AND column_a IS NULL AND column_b IS NULL;
CREATE UNIQUE INDEX table_a_col_a_b_index ON table_a (table_b_id, column_a, column_b)
WHERE column_a IS NOT NULL AND column_b IS NOT NULL AND column_c IS NULL;
CREATE UNIQUE INDEX table_a_col_a_c_index ON table_a (table_b_id, column_a, column_c)
WHERE column_a IS NOT NULL AND column_c IS NOT NULL AND column_b IS NULL;
CREATE UNIQUE INDEX table_a_col_b_c_index ON table_a (table_b_id, column_b, column_c)
WHERE column_b IS NOT NULL AND column_c IS NOT NULL AND column_a IS NULL;
如果您想允许多个 NULL
列,那么这就是常规唯一索引或约束的作用:
unique (a, b, c)
如果不希望NULL
的值重复,那么最简单的方法就是将它们默认为一个共同的值,例如-1
:
unique (coalesce(a, -1), coalesce(b, -1), coalesce(c, -1))
这可能并非在所有情况下都有效,但在许多情况下都有效,因为 -1
(或其他一些值)未以其他方式使用。