空值不是唯一的

时间:2011-10-13 10:33:54

标签: database postgresql null

我在postgres上有这样的行:

 name | address | college 

 john | rome    |
 john | rome    |
 max  | tokyo   |

我创建了一个这样的表:

create test (
name    varchar(10),
address varchar(20),
college varchar(20),
constraint test_uq unique (name,address,college);

如何使空值变为唯一,因此输出可以是这样的:

 name | address | college 

 john | rome    |
 max  | tokyo   |

4 个答案:

答案 0 :(得分:2)

Postgres文档claims此行为符合SQL标准:

  

通常,当存在两个或更多时,违反了唯一约束   表中包含所有列的值的行   约束是平等的。但是,不考虑两个空值   在这个比较中相等。这意味着即使存在独特的   约束可以存储包含null的重复行   至少一个受约束列中的值。这种行为   符合SQL标准[。]

一种可能性是重新考虑您的架构(说实话,name+address+college上的唯一性约束在您的示例中并没有完全有意义。)

答案 1 :(得分:2)

如果您只需要查询结果中的唯一记录,请使用SELECT DISTINCT

 
postgres=# SELECT * FROM test;
 name | address | college 
------+---------+---------
 john | rome    | 
 john | rome    | 
 max  | tokyo   | 
(3 rows)

postgres=# SELECT DISTINCT * FROM test;
 name | address | college 
------+---------+---------
 john | rome    | 
 max  | tokyo   | 
(2 rows)

如果要强制忽略空值的唯一记录,则必须创建conditional unique index

postgres=# CREATE UNIQUE INDEX test_index ON test (name, address) WHERE college IS NULL;
CREATE INDEX
postgres=# INSERT INTO test (name, address) VALUES ('john', 'rome');
INSERT 0 1
postgres=# INSERT INTO test (name, address) VALUES ('max', 'tokyo');
INSERT 0 1
postgres=# INSERT INTO test (name, address, college) VALUES ('john', 'rome', 'college');
INSERT 0 1
postgres=# INSERT INTO test (name, address) VALUES ('john', 'rome');
ERROR:  duplicate key value violates unique constraint "test_index"
DETAIL:  Key (name, address)=(john, rome) already exists.

HTH

答案 2 :(得分:0)

如果你把它作为主键,而不是一个唯一的约束,那就可以了。为此,列college必须是NOT NULL并使用(例如)空字符串而不是NULL值。 或者您正在寻找查询?

答案 3 :(得分:0)

NULL未知,因此NULL值等于NULL永远不会为真。要解决这个问题,请这样做。

为您的大学创建一个新的查找表。在该表中有一个值为None的记录。然后将一个外键放入新的大学查询表。

这是伪代码,所以你可能不得不弄乱它以使它工作,但这是基本的想法。

CREATE TABLE college(college_id SERIAL PRIMARY KEY,college_type);
INSERT INTO college(college_type)
SELECT 1,None;


create test (
name varchar(10),
address varchar(20),
college_id INTEGER NOT NULL DEFAULT 1,
constraint test_uq unique (name,address,college_id);