假设我有一个带有主键parent
的表id
,带有外键child
的表parent_id
和一个“布尔”列(约束为0)或1),我们称之为is_initial
。
我想要做的是对child
施加约束,以便对于parent_id
的特定值,只有一行is_initial = 1
。 is_initial = 0可以有任意数量的行。
这可以通过约束来完成吗?我不想添加触发器。
感谢。
答案 0 :(得分:4)
您可以使用唯一索引执行此操作:
create unique index initialindex on child(
case when is_initial <> 1 then parent_id || 'xx' || child_id
else null
end
);
现在,在尝试使用is_initial = 1插入第二行后,您应该会遇到约束违规。
答案 1 :(得分:3)
在这里,我相信我明白你在寻找什么
请注意唯一索引中的更改:
create unique index childTable_initialIndex on childTable(
case when is_initial = 1 then parent_id
else null
end);
create table childTable(parent_id number, child_id number primary key, is_initial number, somethingelse varchar2(50) );
create unique index childTable_initialIndex on childTable(
case when is_initial = 1 then parent_id
else null
end);
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,1,0,'works');
1 rows inserted.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,1,0,'will not work if childId is pk');
SQL Error: ORA-00001: unique constraint (SYS_C0062138) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,2,1,'works3');
1 rows inserted.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (1,3,1,'should not work');
SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,4,0,'works4');
1 rows inserted.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,5,0,'works5');
1 rows inserted.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,6,1,'works6');
1 rows inserted.
insert into childTable(parent_id, child_id, is_initial,somethingelse) values (2,7,1,'should not work');
SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
--we should only see things that work
select * from childTable
/
--this should not work, since works already has the 1/1 is_initial 1
update childTable
set somethingelse = 'Should not work!'
, is_initial = 1
where somethingelse = 'works';
SQL Error: ORA-00001: unique constraint (CHILDTABLE_INITIALINDEX) violated
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
结果如下:
PARENT_ID CHILD_ID IS_INITIAL SOMETHINGELSE
--------- -------- ---------- --------------------------------------------------
1 1 0 works
1 2 1 works3
2 4 0 works4
2 5 0 works5
2 6 1 works6
答案 2 :(得分:2)
以更“关系”的方式执行 - 不要使用child.is_initial
,而是使用可以为NULL的parent.initial_child_id
,并且是child
表的FOREIGN KEY。
由于initial_child_id
位于parent
表格而非child
,因此每个家长只能有一个。
你的DDL看起来像这样:
CREATE TABLE parent (
id INT,
initial_child_id INT,
PRIMARY KEY (id)
);
CREATE TABLE child (
child_id INT,
parent_id INT NOT NULL,
PRIMARY KEY (child_id)
);
ALTER TABLE parent ADD FOREIGN KEY (initial_child_id) REFERENCES child;
ALTER TABLE child ADD FOREIGN KEY (parent_id) REFERENCES parent;