2011-07-22 55 views
0

我有這樣的:修改表列加約束,其中列不爲空

alter table supplier 
add constraint supplier_unique 
unique (supplier_id) where supplier_id is not null; 

但我得到一個錯誤。

產生的定義應該是:

CREATE UNIQUE INDEX supplier_unique 
ON supplier (supplier_id) WHERE (supplier_id IS NOT NULL) 

感謝。

+0

也許你正在尋找的是插入/更新而不是約束的觸發器 – Seph

回答

4

A unique constraint在PostgreSQL中沒有WHERE子句,因此在「where」處得到語法錯誤。在任何情況下,supplier_id is not null沒有必要用一個唯一約束:

在一般情況下,當有在所有列的值包含在約束的表不止一個行的唯一約束被違反等於。然而,在這個比較中,兩個空值不被認爲是相等的。這意味着即使存在唯一約束,也可以在至少一個受約束的列中存儲包含空值的重複行。此行爲符合SQL標準,...

因此,所有你需要的是這樣的:

alter table supplier 
add constraint supplier_unique 
unique (supplier_id); 

而且你的唯一約束將被添加,你可以有supplier_id IS NULL多行,而你」會得到您的索引作爲唯一約束的副作用。

但是,如果你想創建索引,直接就可以用create a partial index謂詞:

當WHERE子句,創建一個部分索引。部分索引是一個索引,其中只包含表的一部分的條目,通常是比表的其餘部分對索引更有用的部分。
[...]
另一個可能的應用是使用WHERE和UNIQUE在表的一個子集上執行唯一性。

但在空值的情況下,supplier_id IS NOT NULL部分索引,不會做的唯一事情,因爲PostgreSQL的唯一約束已經允許多個NULL值(標準可能因爲因爲x = NULL是假的所有x) 。

所以,如果你的意圖是太限制非NULL值的唯一性,那麼你不需要你的部分索引;但是,如果你只是想避免索引NULL值,那麼你可以通過CREATE INDEX(而不是ALTER TABLE)來完成。我不知道是否將NULL從你的索引中刪除將有任何明顯的效果。

我認爲混亂的一部分(你和我的)是,UNIQUE是一個約束和索引。當您將其創建爲索引時,您可以包含一個WHERE,但在將其創建爲約束時不能創建該索引。這當然是不一致的。

+0

如果您向可空列中插入多個NULL,MSSQL將引發重複鍵錯誤。 MSSQL2008增加了對[過濾索引]的支持(http://msdn.microsoft.com/en-us/library/cc280372.aspx)。 – gordy

+1

@gordy:(1)這與標準相反,恕我直言,有點愚蠢,(2)這是關於PostgreSQL的。 –

+0

目的是讓'supplier_id'爲null,但是當它的值被輸入時,它必須是別人唯一的。 – Victor