2017-06-17 45 views
0

我得到了2個表,PersonsRelationships2個表之間的Oracle SQL Check約束

Persons表只有2個字段:IDAge

Relationships有3個領域:Person_IDRelative_IDRelation

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

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

感謝

+0

到目前爲止你做了什麼? –

+0

我解決了其他問題,我有:我也有一個「工作類」字段,我想成爲10個可能的值之一,所以我創建了一個「Workclasses」表,並創建一個外鍵約束從persons_workclass字段到workclasses_name字段。 –

回答

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

ORA-04079:無效觸發器規範 04079. 00000 - 「無效觸發器規範」 *原因:create TRIGGER語句無效。 *操作:檢查語句的正確語法。 –

+0

在「函數」語句之前應該存在「聲明」。順便說一句,我建議你使用像1,2,3一樣的關係字段數字與由「孩子」,「已婚」等組成的查找表等。 –

+0

是的,我已經改變了它,我已經寫在記事本中))感謝你 – Vecchiasignora

1

CHECK約束(使用其技術含義的短語),具有參照約束的例外,從兩個不同的表上的數據無法編碼的限制。

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

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 

當然,你必須創建物化視圖日誌第一,等等。所以,這個物化視圖將不得不爲每個無效的關係一行。然後在物化視圖上創建一個約束,例如條件爲flag = 0。 (或者,簡單一點:改變MV以select null as flag from....,使列flagnot null在MV。)

每當插入一個無效的行到relationships表試圖,物化視圖將更新新的一排;但MV上的檢查約束阻止了這一點,所以整個事務將失敗。

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

請注意,這會在多用戶設置中失敗,因爲它依賴於只能在當前會話中看到的數據進行驗證;它不會看到其他會話尚未提交的數據。 –