我有两张桌子,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
由于
答案 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;