簡體   English   中英

2個表之間的Oracle SQL Check約束

[英]Oracle SQL Check constraint between 2 tables

我有2張桌子, PersonsRelationships

現在,“ Persons表只有2個字段: IDAge

Relationships具有3個字段: Person_IDRelative_IDRelation

我想做的很簡單:在插入\\更新到Relationships我要檢查以下內容:

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

謝謝

您應該創建觸發器。

嘗試這個

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;

除參照約束外,檢查約束(使用其技術含義中的短語)無法對來自兩個不同表的數據的約束進行編碼。

您可以使用的一種技術是創建實例化視圖並對視圖進行約束。 例如:

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上的檢查約束阻止了這種情況,因此整個交易將失敗。

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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM