假设B和C都是子类,A是超类。 B和C不能具有相同的id
(不相交)
CREATE TABLE a(id integer primary key);
CREATE TABLE b(id integer references a(id));
CREATE TABLE c(id integer references a(id));
insert into a values('1');
insert into a values('2');
insert into b values('1');
insert into c values('2');
我可以使用触发器来阻止表B和C中出现相同的id
吗?
答案 0 :(得分:1)
“b和c不能有相同的ID”
因此,您希望强制实施互斥关系。在数据建模中,这称为弧。 Find out more。
我们可以在没有触发器的表之间实现弧,方法是使用type
列来区分子类型,如下所示:
create table a (
id integer primary key
, type varchar2(3) not null check (type in ( 'B', 'C'))
, constraint a_uk unique (id, type)
);
create table b (
id integer
, type varchar2(3) not null check (type = 'B')
, constraint b_a_fk foreign key (id, type) references a (id, type)
);
create table b (
id integer
, type varchar2(3) not null check (type = 'C')
, constraint c_a_fk foreign key (id, type) references a (id, type)
);
超类型表除了主键外还有一个唯一的键;这为子类型表上的外键提供了参考点。我们仍然保留主键以确保id
的唯一性。
子类型表具有type
列的冗余实例,冗余,因为它包含固定值。但是这有必要引用复合唯一键的两列(而不是主键,更常见)。
这种密钥组合确保了如果超类型表具有记录id=1, type='B'
,则子类型表C中没有id=1
的记录。
答案 1 :(得分:0)
您可以使用Oracle序列:
CREATE SEQUENCE multi_table_seq;
INSERT INTO A VALUE(1);
INSERT INTO A VALUE(2);
INSERT INTO B VALUE(multi_table_seq.NEXTVAL()); -- Will insert 1 in table B
INSERT INTO C VALUE(multi_table_seq.NEXTVAL()); -- Will insert 2 in table C
...
使用触发器:
-- Table B
CREATE TRIGGER TRG_BEFORE_INSERT_B -- Trigger name
BEFORE INSERT -- When trigger is fire
ON A -- Table name
DECLARE
v_id NUMBER;
BEGIN
v_id := multi_table_seq.NEXTVAL();
BEGIN
SELECT TRUE FROM C WHERE id = v_id;
RAISE_APPLICATION_ERROR(-20010, v_id || ' already exists in table C');
EXCEPTION WHEN NO_DATA_FOUND -- Do nothing if not found
END;
END;
同样触发表C,检查表B中是否存在id
答案 2 :(得分:0)
设计明智这不好,但我们可以使用下面的代码片段来完成。您可以在表b
上创建类似的触发器CREATE TABLE a(id integer primary key);
CREATE TABLE b(id integer references a(id));
CREATE TABLE c(id integer references a(id));
create or replace trigger table_c_trigger before insert on c for each row
declare
counter number:=0;
begin
select count(*) into counter from b where id=:new.id;
if counter<>0 then
raise_application_error(-20001, 'values cant overlap between c and b');
end if;
end;
insert into a values('1');
insert into a values('2');
insert into b values('1');
insert into b values('2');
insert into c values('2');