简体   繁体   English

如何在Oracle中检查重叠约束?

[英]How to check overlap constraints in Oracle?

Suppose B and C are both subclass and A is a superclass. 假设B和C都是子类,而A是超类。 B and C can not have same id (disjoint) 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');

Could I use a trigger to prevent the same id appearing in tables B and C? 我可以使用触发器来防止在表B和C中出现相同的id吗?

"b and c can not have same id" “ b和c不能具有相同的ID”

So you want to enforce a mutually exclusive relationship. 因此,您想强制执行互斥关系。 In data modelling this is called an arc. 在数据建模中,这称为弧。 Find out more . 了解更多

We can implement an arc between tables without triggers by using a type column to distinguish the sub-types like this: 我们可以使用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)
);

The super-type table has a unique key in addition to its primary key; 超级类型表除了具有主键外,还具有唯一键。 this provides a reference point for foreign keys on the sub-type tables. 这为子类型表上的外键提供了参考点。 We still keep the primary key to insure uniqueness of id . 我们仍然保留确保id唯一性的主键。

The sub-type tables have a redundant instance of the type column, redundant because it contains a fixed value. 子类型表具有type列的冗余实例,该冗余实例是冗余的,因为它包含固定值。 But this is necessary to reference the two columns of the compound unique key (and not the primary key, as is more usual). 但这是必须引用复合唯一键的两列(而不是通常的主键)。

This combination of keys ensures that if the super-type table has a record id=1, type='B' there can be no record in sub-type table C where id=1 . 这种键组合确保如果超类型表的记录id=1, type='B' ,则子类型表C中id=1记录就不会存在。

You can use Oracle Sequence: 您可以使用Oracle Sequence:

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
...

With trigger: 带扳机:

-- 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;

And same trigger for table C who check if id exists in table B 和表C相同的触发器,检查表B中是否存在ID

Design wise this is not good but we can do it using the below snippet. 从设计的角度来看,这不是很好,但是我们可以使用下面的代码片段来做到这一点。 You can create a similar trigger on table b 您可以在表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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM