2009-07-24 100 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');