2009-07-24 102 views
2

我有一個表「富」,看起來像Postgres的:如何防止INSERT在特殊情況下

ID | NAME 
------+---------------------------- 
    123 | PiratesAreCool 
    254 | NinjasAreCoolerThanPirates 

和第二表「酒吧」

SID | ID | created | dropped 
------+------+------------+----------- 
    9871 | 123 | 03.24.2009 | 03.26.2009 
    9872 | 123 | 04.02.2009 | 

bar.ID是一個參考(國外鍵)到foo.ID

現在我想阻止你可以插入一個新的記錄到'欄',當有一個記錄具有相同的ID和bar.dropped爲空記錄。

所以,當「酒吧」看起來像上面

INSERT INTO BAR VALUES ('9873','123','07.24.2009',NULL); 

應該被禁止,但

INSERT INTO BAR VALUES ('9873','254','07.24.2009',NULL); 

應該被允許(因爲沒有「打開」欄中記錄爲「NinjasAreCoolerThanPirates 「)。

我該怎麼做? 我希望我的問題很清楚,有人可以幫助我。

回答

3

嗯,這應該足以創建一個唯一的索引。

create unique index ix_open_bar on bar (id, dropped); 

當然,這也有,你不能每天降一欄兩次的效果(除非該下降是時間戳這將風險降到最低)

事實上,我注意到,Postgres的有對於部分索引支持:

create unique index ix_open_bar on bar (id) where dropped is null; 

更新: 一些測試後,唯一約束不執行對空值,但部分指標仍然可以工作。

如果你不想使用部分索引,這可能工作,以及:

create unique index ix_open_bar on bar(id, coalesce(dropped, 'NULL')); 

然而,使用聚結時,你需要對他們有相同的數據類型(所以如果是下降一個時間戳,您需要改爲將'NULL'改爲時間戳值)。

+0

對空列的唯一索引不會這樣的。 – Draemon 2009-07-24 14:36:30

+0

是的,更新了答案。不知道這只是Postgres的事情,我記得它在其他地方工作。 – 2009-07-24 14:52:19

+0

好吧,經過一些測試「在條形碼(id)上創建唯一索引ix_open_bar,其中drop爲null;」似乎是最好的解決方案。謝謝。 – sloth 2009-07-24 15:00:46

3

這隻會插入一條記錄,如果沒有在酒吧的「開放式」記錄您的ID

INSERT INTO bar 
SELECT '9873','254','07.24.2009',NULL 
WHERE NOT EXISTS(SELECT 1 FROM bar WHERE ID='254' AND dropped IS NULL) 
2

設置一個觸發器在桌子上bar上插入檢查,看看如果當前行的如果已經存在,則ID已經存在並拒絕它。

我不知道具體的Postgres的語法,但它應該工作是這樣的:

CREATE TRIGGER trigger_name BEFORE INSERT ON bar 
IF EXISTS (
    SELECT 1 
    FROM bar 
    WHERE bar.ID = inserted.ID 
    AND bar.dropped IS NULL 
) 
BEGIN 
    // raise an error or reject or whatever Postgres calls it. 
END 

然後每當你嘗試插入bar,該觸發器會檢查,如果事情已經存在,並且拒絕如果是這樣。如果bar.dropped不爲空,它將允許插入很好。

如果有人知道正確的語法,請隨時編輯我的答案。

2

您可以使用WHERE子句創建部分索引。爲了你的目的,這可能會做;

CREATE UNIQUE INDEX my_check on bar(id) where dropped is null; 

假設ID 124不存在於表,這將是允許的,但只有一個記錄可以有下降= NULL對於給定ID:

INSERT INTO BAR VALUES ('9873','124','07.24.2009',NULL); 

,這將允許羯羊或不是124已經存在

INSERT INTO BAR VALUES ('9873','124','07.24.2009','07.24.2009'); 

如果125已經存在,這將不被allowd

INSERT INTO BAR VALUES ('9873','125','07.24.2009',NULL); 

但這將

INSERT INTO BAR VALUES ('9873','125','07.24.2009','07.24.2009');