2013-04-26 168 views
50

我想添加一個約束,只強制在表的一部分列的唯一性。Postgresql:有條件的唯一約束

ALTER TABLE stop ADD CONSTRAINT myc UNIQUE (col_a) WHERE (col_b is null); 

WHERE以上部分是一廂情願。

這樣做的任何方式?還是應該回到關係圖板?

+0

這是已經在這裏找到答案:http://stackoverflow.com/questions/469471/how-do-i-alter-a-postgresql-table-and-make-a-column-獨特 – yvesonline 2013-04-26 12:27:51

+2

通常做。請參閱「部分唯一索引」 – 2013-04-26 12:30:18

+10

@yvesonline否,這是一個常規的唯一約束。海報想要一個*部分*唯一的約束。 – 2013-04-26 12:31:12

回答

92

PostgreSQL沒有定義的部分(即有條件的)UNIQUE約束 - 但是,你可以創建部分唯一指數。 PostgreSQL使用唯一的索引來實現唯一的約束,所以效果是一樣的,你只是看不到information_schema中列出的常量。

CREATE UNIQUE INDEX stop_myc ON stop (col_a) WHERE (col_b is null); 

請參閱partial indexes

+13

超級!不直觀的是,「約束」沒有作爲約束出現,但卻給出了'錯誤:重複鍵值違反唯一約束'的錯誤'stop_myc「' – EoghanM 2013-04-26 17:08:38

+2

值得注意的是,這將不允許創建FKs引用那部分獨特的領域。 – amenadiel 2017-10-30 22:02:33

1

它已經說過,PG沒有定義一個部分(即條件)UNIQUE約束。此外文檔中說,唯一約束添加到表的首選方法是ADD CONSTRAINTUnique Indexes

The preferred way to add a unique constraint to a table is ALTER TABLE ... ADD CONSTRAINT. The use of indexes to enforce unique constraints could be considered an implementation detail that should not be accessed directly. One should, however, be aware that there's no need to manually create indexes on unique columns; doing so would just duplicate the automatically-created index.

有使用Exclusion Constraints來實現它的方式,(感謝@dukelion該解決方案)

你的情況它看起來像

ALTER TABLE stop 
    ADD CONSTRAINT stop_col_a_key_part EXCLUDE (col_a WITH =) WHERE (col_b IS null); 
+0

在這種方法你不使用「使用」來定義索引方法,所以這可能會非常緩慢或postgres創建一個默認的索引呢? 該方法是規範的選擇,但沒有更好的選擇! 我認爲你需要一個帶有索引的「使用」從句來使這個選擇更好。 – 2018-02-21 11:40:15