用一句话来总结这种改进就是:
支持唯一性约束和索引将null值视为相同的值。
之前是将null值索引成不同的值,现在可以通过使用unique nulls not distinct创建约束,将null值视为相同的值。
两种unique风格
创建示例表:
CREATE TABLE null_old_style
(
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
val1 TEXT NOT NULL,
val2 TEXT NULL,
CONSTRAINT uq_val1_val2
UNIQUE (val1, val2)
);
CREATE TABLE null_new_style
(
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
val1 TEXT NOT NULL,
val2 TEXT NULL,
CONSTRAINT uq_val1_val2_new
UNIQUE NULLS NOT DISTINCT (val1, val2)
);
支持的数据的变化
在postgresql 14中或更早的版本,唯一性约束将null
与null
视为是不相同的。
这与sql标准是相同的,简而言之,null
表示unknown
。因而,null
值也就不违反唯一性约束。
可以通过插入五行相同的记录到表null_old_style
INSERT INTO null_old_style (val1, val2)
SELECT 'Hello', NULL
FROM generate_series(1, 5)
;
SELECT * FROM null_old_style;
id|val1 |val2|
--+-----+----+
1|Hello| |
2|Hello| |
3|Hello| |
4|Hello| |
5|Hello| |
这个行为是有文档可查,符合预期的。
引入了nulls not distinct
选项后,唯一性约束更加严格,不再支持多个null
值。
INSERT INTO null_new_style (val1, val2)
SELECT 'Hello', NULL;
SELECT * FROM null_new_style;
id|val1 |val2|
--+-----+----+
1|Hello| |
再想插入一个val1
值为'Hello',val2
值为null的记录就会违反唯一性约束:
INSERT INTO null_new_style (val1, val2)
SELECT 'Hello', NULL;
SQL Error [23505]: ERROR: duplicate key value violates unique constraint "uq_val1_val2_new"
Detail: Key (val1, val2)=(Hello, null) already exists.
当然将val1
换成'Hello'之外的一个值,val2
值为null就可以插入了:
INSERT INTO null_new_style (val1, val2)
SELECT 'World', NULL;
id|val1 |val2|
--+-----+----+
1|Hello| |
3|World| |
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接