两个表之间的Oracle SQL Check约束

时间:2017-06-17 07:27:39

标签: sql oracle constraints check-constraints

我有两张桌子,PersonsRelationships

Persons表目前只有2个字段:IDAge

Relationships有3个字段:Person_IDRelative_IDRelation

我想做的很简单:插入\更新到Relationships我想检查以下内容:

if Relation == 'child' and Persons[Person_ID].Age < Persons[Relative_ID].Age:
    Throw Exception

由于

3 个答案:

答案 0 :(得分:1)

你应该创建触发器。

试试这个

CREATE OR REPLACE TRIGGER   my_trg
              BEFORE INSERT OR UPDATE ON Relationships
                 FOR EACH ROW
  declare
     function i_Age(id int) return int is
     li_res int;
     begin
       select p.Age
        into li_res 
        from Persons p 
        where p.ID= id 
         and rownum=1;
        return li_res;
    exception when no_data_found then
    return NULL; --or Throw Exception depend on your logic if some datas not found
     end;

     BEGIN
      IF INSERTING OR UPDATING THEN
          IF :NEW.Relation == 'child' and i_Age(:NEW.Person_ID) < i_Age(:NEW.Relative_ID)  then 
           NULL; --Throw Exception or your logic
          END IF;
      END IF;
   END;

答案 1 :(得分:1)

检查约束(使用其技术含义中的短语),除参考约束外,不能对来自两个不同表的数据进行约束编码。

您可以使用的一种技术是创建物化视图并对视图有约束。例如:

create materialized view relationship_check_mv
build immediate
refresh fast on commit
as
  select 1 as flag
  from   persons       p1
         join
         relationships r  on p1.id = r.person_id
         join
         persons       p2 on p2.id = r.relative_id
  where  r.relationship = 'child'
    and  p1.age < p2.age

当然,您必须首先创建物化视图日志等。因此,此物化视图将为每个INVALID关系创建一行。然后在物化视图上创建约束,例如条件flag = 0。 (或者,更简单一点:将MV更改为select null as flag from....并使MV中的flag列成为not null。)

每当尝试将无效行插入relationships表时,物化视图将使用新行进行更新;但MV上的检查约束阻止了这一点,因此整个事务将失败。

答案 2 :(得分:0)

CREATE OR REPLACE TRIGGER child_parent_age_tr BEFORE INSERT OR UPDATE ON RELATIONSHIPS FOR EACH ROW
    DECLARE 
        child_age NUMBER; 
        parent_age NUMBER;

    BEGIN
        SELECT AGE INTO child_age FROM PERSONS WHERE ID = :NEW.PERSON_ID;
        SELECT AGE INTO parent_age FROM PERSONS WHERE ID = :NEW.RELATIVE_ID;
        IF INSERTING OR UPDATING THEN
            IF :NEW.RELATION = 'child' AND child_age >= parent_age THEN
                RAISE INVALID_NUMBER;
            END IF;
        END IF;
    END;