2012-06-05 88 views
8

PostgreSQL有可能有條件地添加一個外鍵嗎?有條件的PostgreSQL外鍵

喜歡的東西:ALTER TABLE table1 ADD FOREIGN KEY (some_id) REFERENCES other_table WHERE some_id NOT IN (0,-1) AND some_id IS NOT NULL;

具體來說,我的參考表中有所有的正整數(1+),但我需要添加外鍵的表可以包含零(0),零和負一(-1 )而是,所有的含義都有所不同。

注:

我深知,這是窮人表設計,但它是建立10+年前,當我們可以在這一點上不存在的功能和資源巧招。這個系統正在運行數百家零售店,所以要回去改變這個方法可能需要幾個月的時間,這是我們沒有的。

我不能使用觸發器,這必須用外鍵完成。

回答

1

您可以添加其他「影子」列table1保持清潔值(即一切,但0-1)。使用此列進行參照完整性檢查。此陰影列由table1上的一個簡單觸發器更新/填充,它將所有值除0-1寫入陰影列。 0-1都可以映射到null

然後你有參考完整性和你原來的不變的專欄。缺點是:你也有一些觸發和一些冗餘數據。但是,唉,這是傳統模式的命運!

+0

天才!你是對的,它有點難看,但數據庫仍然自我管理,所以它應該做的伎倆! – trex005

+0

啊,你有沒有研究過Postgres源代碼?這可能是一個很酷的功能,您可以通過在幕後完成此操作來添加。 – trex005

+1

@ trex005:我還沒有在PG源上工作過。但是,我時時刻刻都在黑客的名單上冒險,這樣的特點不會受到歡迎。如果你推廣_your_例子(除了'0'和'-1'之外的任何其他內容)並考慮涵蓋所有可能情況的通用語法,你會得到一個非常複雜的語法結構。在規模的另一方面:現有的工具已經無法做到。最終結果是:稀缺資源(開發人員時間/預算)將在其他TODO項目上得到更好的回報。但這只是我的印象。隨時與他們聯繫。 –

2

簡短回答是否,Postgres沒有有條件外鍵。您可能考慮的一些選項是:

  1. 只是沒有FK約束。將此邏輯移入數據訪問層,並且沒有參照完整性。
  2. 允許在列中使用NULL,即使使用FK約束,這也是完全有效的。然後,使用另一列來存儲0-1的含義。
  3. 0-1的引用表中添加一個虛擬行。即使它只是具有假數據,也會滿足FK約束。

希望這會有所幫助!

+1

這些人幾乎我所預料的選項。我會把問題留下一段時間,希望我們錯了。 :) – trex005

+2

選項4始終修改Postgres代碼,它*是*開放源代碼,你知道:) –

+0

非常非常真實.....你的出價是什麼? :o) – trex005

1

您的需求就是相當於這個檢查約束:

create table t (a float check (a >= -1 and a = floor(a) or a is null)); 
+0

是的,但是檢查約束無法檢查另一個表中是否存在行。 –

+0

@MikeChristensen問題說引用的表_具有所有正整數(1 +)_。我知道這是不可能的,但我想他意味着它具有所有整數,沒有差距達到一定限度。這將包括在檢查中添加另一個條件(a <= n)。 –

+1

可能的,我只是假設OP實際上想要一個真正的外鍵。 –

0

這是另一種可能性。使用PG繼承來強制表的分區變爲在標誌列中有+1,否則。 (通常的規則/觸發器來維護這個)。然後只有Has_PLUS_ONE子表和被引用的表之間有FK關係。

+0

使用PG繼承幾乎從來都不是正確的解決方案。他們太有限而且古怪。 – cliffordheath

0

您可以通過檢查約束和外鍵來實現這一點。

CREATE TABLE table1 (some_id INT, some_id_fkey INT REFERENCES other_table(other_id), CHECK (some_id IN (0,-1) OR some_id IS NOT DISTINCT FROM some_id_fkey)); 

(未測試)