【问题标题】:PostgreSQL Unique index compound keyPostgreSQL 唯一索引复合键
【发布时间】:2013-01-19 10:40:27
【问题描述】:

我需要创建一个基于四列的表的限制,其中两个是互斥的,我的意思是,如果一个是NULL,另一个不是。

理想的脚本是这样的:

ALTER TABLE ONLY t_users_prizes
ADD CONSTRAINT t_user_prize_test_circuit_key
UNIQUE (id_event||':'||id_circuit, id_prize, id_user);

但 Postgres 不允许这种连接。

如何实施此限制?

【问题讨论】:

  • 你会允许(1, NULL, 3, 4)(NULL, 1, 3, 4)共存吗?
  • 据我了解,与@Erwin 和 Catcall 答案中暗示的相反,两个互斥列都不能为空。正确的解释是什么?
  • 我们的两个答案都不允许一对 NULL。

标签: sql postgresql null indexing unique-index


【解决方案1】:

NULL 值不违反 UNIQUE 约束 - 两个 NULL 不被视为相等!所以一个简单的UNIQUE 约束不起作用。

你可以用两个partial UNIQUE indexes和一个CHECK constraint来完成它:

CREATE TEMP TABLE foo (
  a int
, b int
, c int NOT NULL
, d int NOT NULL
, CHECK ((a IS NOT NULL AND b IS NULL) OR (b IS NOT NULL AND a IS NULL))
);

CREATE UNIQUE INDEX foo_acd_idx ON foo(a,c,d)
WHERE b is NULL;

CREATE UNIQUE INDEX foo_bcd_idx ON foo(b,c,d)
WHERE a is NULL;

INSERT INTO foo VALUES (NULL,2,3,4);
INSERT INTO foo VALUES (NULL,2,3,4);  -- error! 

我将cd 声明为NOT NULL,以防止进一步的复杂化。

见:

要同时禁止(1, NULL, 3, 4)(NULL, 1, 3, 4),您可以使用COALESCE 的一个索引来代替:

CREATE UNIQUE INDEX foo_xcd_idx ON foo(COALESCE(a,b),c,d);

【讨论】:

  • 很好的答案!这解决了问题并鼓励我在 postgres 中做新的事情。谢谢! (下一个任务:分区表!)
猜你喜欢
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
相关资源
最近更新 更多