2个表之间的Oracle SQL Check约束
我得到了2个表,Persons
和Relationships
。2个表之间的Oracle SQL Check约束
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;
ORA-04079:无效触发器规范 04079. 00000 - “无效触发器规范” *原因:create TRIGGER语句无效。 *操作:检查语句的正确语法。 –
在“函数”语句之前应该存在“声明”。顺便说一句,我建议你使用像1,2,3一样的关系字段数字与由“孩子”,“已婚”等组成的查找表等。 –
是的,我已经改变了它,我已经写在记事本中))感谢你 – Vecchiasignora
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....
,使列flag
是not null
在MV。)
每当插入一个无效的行到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;
请注意,这会在多用户设置中失败,因为它依赖于只能在当前会话中看到的数据进行验证;它不会看到其他会话尚未提交的数据。 –
到目前为止你做了什么? –
我解决了其他问题,我有:我也有一个“工作类”字段,我想成为10个可能的值之一,所以我创建了一个“Workclasses”表,并创建一个外键约束从persons_workclass字段到workclasses_name字段。 –