2010-03-01 83 views
0

我有兩個表:甲板(ID)和卡(甲板,顏色,值)插入幾個行以滿足約束

甲板具有這些約束:

  • CHECK (fifty_two_cards_deck(id))
  • PRIMARY KEY (id)

    CREATE FUNCTION fifty_two_cards_deck(甲板整數)返回Boolean 語言SQL STABLE嚴格 AS $ $ SELECT COUNT(*)= 52 FROM card WHERE deck = $ 1 $ $;

和卡有這些約束:

  • FOREIGN KEY (deck) REFERENCES deck(id)
  • PRIMARY KEY (deck, color, value)

我怎樣才能插入一個新的平臺?

我嘗試這樣做:

begin transaction; 
INSERT INTO "public"."deck" ("id") VALUES (nextval('deck_id_seq'::regclass)); 
INSERT INTO "public"."card" ("deck", "color", "value") VALUES ('1', enum_first(null::Suit), enum_first(null::Symbol)); 

end transaction 

(我不得不編輯fifty_two_cards_deck是用於測試目的的one_card_deck) 但我得到這個錯誤:

SQL error:

ERROR: new row for relation "deck" violates check constraint "fifty_two_cards_deck"

In statement: begin transaction; INSERT INTO "public"."deck" ("id") VALUES (nextval('deck_id_seq'::regclass)); INSERT INTO "public"."card" ("deck", "color", "value") VALUES ('1', enum_first(null::Suit), enum_first(null::Symbol));

end transaction

我怎樣才能解決這個無需拆卸限制?

編輯:解

THX馬格納斯Hagander我得到它的工作是這樣的(設置外鍵可延遲後):

begin transaction; 

SET CONSTRAINTS ALL DEFERRED; 

INSERT INTO "public"."deck-card" ("deck", "position", "color", "value") VALUES (1, 0, enum_first(null::suit), enum_first(null::Symbol)); 
INSERT INTO "public"."deck" ("id") VALUES (1); 

end transaction 

回答

1

,如果你與DEFERRABLE外鍵它可能工作,然後將其設置爲DEFERRED。然後你插入「卡」表第一個,然後進入「甲板」。檢查約束在插入時執行(因此,在「卡」存在的條目之前),並且不能推遲到事務結束。

但是這實際上並沒有解決你的約束被破壞並應該被刪除的事實)CHECK約束只會檢查進入「deck」的行。但是,一旦行被插入,您仍然可以在「卡」表中添加更多行或刪除行,並且CHECK約束不會發出抱怨 - 直到下次嘗試修改「卡組」爲止。

+0

實際上,由於卡片上的主鍵以及顏色和值都是枚舉這一事實,我無法在卡組中添加更多卡片。但我可以刪除一些。 我要看看觸發器是否可以解決這個問題(例如,在刪除行之前檢查fifty_two_cards_deck(row.deck)是否返回true) 爲什麼建議刪除約束而不是修復此問題?我一直認爲更有用的限制是他最好的。 – Mathieu 2010-03-01 11:24:01

+0

您可以使用觸發器修復它,但這可能會讓您陷入併發問題。刪除它的原因是在上面的段落中 - 你試圖使用一個CHECK約束來實現它不打算做的事情,並且有很多陷阱 - 其中只有一個允許DELETE。 – 2010-03-01 22:20:04

相關問題