空值不是唯一的

发布于 2024-12-09 21:35:18 字数 427 浏览 0 评论 0原文

我在 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   |

I have rows like these on postgres:

 name | address | college 

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

I create a table like this:

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

How can I make null values become unique, so the output can be like this:

 name | address | college 

 john | rome    |
 max  | tokyo   |

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

霊感 2024-12-16 21:35:18

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

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

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

Postgres documentation claims that this behaviour is compliant with the SQL standard:

In general, a unique constraint is violated when there are two or more
rows in the table where the values of all of the columns included in
the constraint are equal. However, two null values are not considered
equal in this comparison. That means even in the presence of a unique
constraint it is possible to store duplicate rows that contain a null
value in at least one of the constrained columns. This behavior
conforms to the SQL standard[.]

One possibility is to rethink your schema (to be honest, a uniqueness constraint on name+address+college doesn't make a whole lots of sense in your example).

在你怀里撒娇 2024-12-16 21:35:18

如果您只需要查询结果中的唯一记录,请使用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)

如果您想强制执行唯一记录忽略空值,则必须创建一个条件唯一索引

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

If you just need unique records in the query result use 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)

If you want to enforce unique records ignoring null values you must create a 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

无风消散 2024-12-16 21:35:18

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);

NULL is unknown so a value of NULL being equal to NULL can never be true. To work around this law do this.

Create a new look-up table for your colleges. In that table have a record with the value None. Then put a Foreign Key to the new college look-up table.

This is pseudo code so you may have to mess with it to make it work, but here is the basic idea.

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);
初熏 2024-12-16 21:35:18

如果将其设为主键,而不是唯一约束,它就会起作用。为此,college 列必须为 NOT NULL 并使用(例如)空字符串而不是 NULL 值。
或者您正在寻找查询?

If you make it a primary key, instead of a unique constraint, it would work. For that, the column college would have to be NOT NULL and use (for instance) empty strings instead of NULL values.
Or are you looking for a query?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文