Ala*_*lan 19 postgresql null unique
我最近注意到Postgres在具有唯一约束的列中处理NULL的方式不一致.
考虑一个人的表:
create table People (
pid int not null,
name text not null,
SSN text unique,
primary key (pid)
);
Run Code Online (Sandbox Code Playgroud)
SSN列应保持唯一.我们可以检查:
-- Add a row.
insert into People(pid, name, SSN)
values(0, 'Bob', '123');
-- Test the unique constraint.
insert into People(pid, name, SSN)
values(1, 'Carol', '123');
Run Code Online (Sandbox Code Playgroud)
第二个插入失败,因为它违反了SSN上的唯一约束.到现在为止还挺好.但是让我们尝试一下NULL:
insert into People(pid, name, SSN)
values(1, 'Carol', null);
Run Code Online (Sandbox Code Playgroud)
这样可行.
select *
from People;
0;"Bob";"123"
1;"Carol";"<NULL>"
Run Code Online (Sandbox Code Playgroud)
唯一列将为空.有趣.Postgres如何断言null在任何方面都是唯一的,或者不是唯一的?
我想知道我是否可以在唯一列中添加两行null.
insert into People(pid, name, SSN)
values(2, 'Ted', null);
select *
from People;
0;"Bob";"123"
1;"Carol";"<NULL>"
2;"Ted";"<NULL>"
Run Code Online (Sandbox Code Playgroud)
我可以.现在SSN列中有两行NULL,即使SSN应该是唯一的.
在Postgres的文件说,对于唯一约束的目的,空值是不相等的.
好的.我可以看出这一点.在null处理中这是一个很好的微妙之处:通过将唯一约束列中的所有NULL都视为不相交,我们会延迟唯一约束强制执行,直到有一个实际的非null值作为执行的基础.
那很酷.但这是Postgres失去我的地方.如果唯一约束列中的所有NULL都不相等,正如文档所述,那么我们应该在select select查询中看到所有空值.
select distinct SSN
from People;
"<NULL>"
"123"
Run Code Online (Sandbox Code Playgroud)
不.那里只有一个空值.似乎Postgres有这个错误.但我想知道:还有另一种解释吗?
编辑:
Postgres文档确实指出"在这种比较中,空值被认为是相等的".在SELECT DISTINCT部分.虽然我不明白这个概念,但我很高兴在文档中详细阐述.
Pet*_*aut 11
最重要的是,PostgreSQL用null做了它,因为SQL标准这样说.
Nulls显然很棘手,可以用多种方式解释(未知值,缺失值等),因此当SQL标准最初编写时,作者必须在某些地方进行一些调用.我说时间已证明它们或多或少是正确的,但这并不意味着不可能有另一种数据库语言轻微地(或疯狂地)处理未知和缺失的值.但是PostgreSQL实现了SQL,所以就是这样.
正如在不同的答案中已经提到的那样,Jeff Davis撰写了一些关于处理空值的好文章和演示文稿.
NULL被认为是唯一的,因为NULL它并不代表缺少值。NULL列中的A 是未知值。比较两个未知数时,您不知道它们是否相等,因为您不知道它们是什么。
想象一下,您有两个标有A和B的框。如果您不打开框并且看不到内部,则您永远都不知道其中的内容。如果系统询问您“这两个盒子的内容是否相同?” 您只能回答“我不知道”。
在这种情况下,PostgreSQL将做同样的事情。当要求比较两个NULLS时,它说“我不知道”。这与NULLSQL数据库中疯狂的语义有关。链接到的@JackPDouglas文章是了解NULLs行为的一个很好的起点。请注意:它因供应商而异。
| 归档时间: |
|
| 查看次数: |
7514 次 |
| 最近记录: |