[英]Oracle SQL Check constraint between 2 tables
我有2張桌子, Persons
和Relationships
。
現在,“ Persons
表只有2個字段: ID
和Age
。
Relationships
具有3個字段: Person_ID
, Relative_ID
和Relation
我想做的很簡單:在插入\\更新到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.