2013-06-03 163 views
12

PostgreSQL有可能在字符列上創建可延遲的唯一約束,但不區分大小寫嗎?可推遲,不區分大小寫的唯一約束

假設以下基本表:

CREATE TABLE sample_table ( 
    my_column VARCHAR(100) 
); 

如果不需要延遲的約束,這是與函數創建唯一索引一樣簡單,例如:

CREATE UNIQUE INDEX my_unique_index ON sample_table(UPPER(my_column)); 

延遲的約束檢查需要創建明確的約束,例如:

ALTER TABLE sample_table 
ADD CONSTRAINT my_unique_constraint UNIQUE(my_column) 
DEFERRABLE INITIALLY IMMEDIATE; 

Andunfortunatel y不可能在唯一約束中使用任意函數。

一種可能的解決方法是創建具有與my_column相同內容的其他列,但是大寫,在每次更新/插入後通過觸發更新,然後在此人工列上創建可延遲的唯一約束。然而,這聽起來像一個非常醜陋的黑客。

或者,應該可以使用CREATE CONSTRAINT TRIGGER並手動檢查不區分大小寫的唯一性(當然,常規索引仍然是必需的)。這聽起來有點過於複雜,對於這樣一個簡單的(而且很流行的,我想)的要求。

圍繞此限制有沒有更簡單和/或更優雅的方法?

+0

你的Postgres版本? –

+0

現在是9.1。然而,如果在較新版本中有一個很好的解決方案,我會非常樂意閱讀它:) –

+1

檢查'EXCLUDE'約束。可以設置它們,以便像不區分大小寫的'UNIQUE'一樣操作。 –

回答

11

您可以通過使用由相同名稱的附加模塊提供的特殊類型citext來規避限制。引述手冊:

citext模塊提供不區分大小寫的字符串類別, citext。實質上,比較值時它內部調用較低。 否則,它的行爲幾乎完全像text

它確切地處理您的案件。每個數據庫運行一次:

CREATE EXTENSION citext; 

然後,您可以:

CREATE TABLE sample_table ( 
    my_column citext 
    ,CONSTRAINT my_unique_constraint UNIQUE(my_column) 
    DEFERRABLE INITIALLY IMMEDIATE 
); 
+0

太棒了,正是我想在這種情況下(仍然希望某些解決方案允許在約束中的功能))。對於Ubuntu用戶 - 'citext'在'postgresql-contrib'包中。 –

+1

我不應該添加一個擴展名,讓字符串類型不區分大小寫...... postgress應該提供更好的解決方案 – Leonel

+6

@Leonel:您的意見已被注意到。不過,不知道它是如何轉化爲我的答案downvote。如果你有一個特定的問題需要解決,考慮發佈一個問題,有各種情況下可以解決,而無需安裝擴展名'citext'。但是安裝它並沒有什麼錯,它實際上只是'CREATE EXTENSION citext;'的問題。該模塊是發佈的一部分,由同一團隊維護和發佈,並進行了全面測試。它不在覈心版本的唯一原因是因爲大多數人不需要它。它是「Postgres」,順便說一句,PostgreSQL的簡稱。 –