问题
I got 2 tables, Persons
and Relationships
.
The Persons
table got only 2 fields for now: ID
and Age
.
Relationships
have 3 fields: Person_ID
, Relative_ID
and Relation
What I wanna do is simple: on insertion\update to Relationships
I want to check the following:
if Relation == 'child' and Persons[Person_ID].Age < Persons[Relative_ID].Age:
Throw Exception
Thanks
回答1:
You should create trigger.
Try this
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;
回答2:
Check constraints (using the phrase in its technical meaning), with the exception of referential constraints, can't encode constraints on data from two different tables.
One technique you can use is to create a materialized view and have a constraint on the view. For example:
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
Of course, you will have to create materialized view logs first, etc. So, this materialized view will have one row for each INVALID relationship. Then create a constraint on the materialized view, for example for the condition flag = 0
. (Or, a bit simpler: change the MV to select null as flag from....
and make the column flag
to be not null
in the MV.)
Whenever an attempt to insert an invalid row into the relationships
table is made, the materialized view would be updated with a new row; but the check constraint on the MV prevents that, so the entire transaction will fail.
回答3:
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;
来源:https://stackoverflow.com/questions/44601943/oracle-sql-check-constraint-between-2-tables