在插入或更新主 table 后插入另一个 table 的复合触发器
Compound trigger to insert into another table after insert or update into the main table
我正在研究复合触发器,但我很难弄清楚如何让它发挥作用。触发器在 人 table 上。有一列woman_act。如果插入了一个新行并且该列不为空,那么我们需要将该行插入 v_changes table 或者如果该列是从 null 到 'X' 而不是将该行插入 v_changes table .使用 COMPOUND 触发器是因为我得到 变异 table 并且发生这种情况是因为我从 select.
插入
这是逻辑
--Insert with person.woman_act == ‘ ’ do nothing
--Insert with person.woman_act == ‘X’ insert with is_vawa = 1/true
--Update with person.woman_act changed from ‘ ‘ to ‘X’ insert with is_woman_act = 1/true
create table person (
id number primary key,
reg_number varchar2(9),
last_name charchar2(255),
first_name charchar2(255),
dob date,
birth_c_id number(38,0),
cit_country_id number(38,0),
poe_id number(38,0),
woman_act varchar2(1) check (woman_act in (null, 'X'))
);
create table v_changes (
id number primary key,
person_id number not null,
reg_number varchar2(9),
last_name charchar2(255),
first_name charchar2(255),
dob date,
b_country varchar2(255),
cit_country varchar2(255),
poe varchar2(30),
is_woman_act number(1,0)
);
create table country_code (
id number primary key,
valid_code varchar2(255)
);
create table loc_code (
id number primary key,
valid_code varchar2(255)
);
这是我的触发器。非常感谢任何想法和建议。
CREATE OR REPLACE TRIGGER v_changes_trg
FOR INSERT OR UPDATE OF woman_act ON person
COMPOUND TRIGGER
TYPE t_vawa_type IS TABLE OF person.woman_act%TYPE;
t_vawa t_vawa_type := t_vawa_type();
TYPE t_v_id IS TABLE OF person.id%TYPE;
v_ids t_v_id :=t_v_id();
BEFORE STATEMENT IS
t_vawas := t_vawa_type();
v_ids :=t_v_id();
END BEFORE STATEMENT;
BEFORE EACH ROW IS
t_vawa_id person.id%ROWTYPE;
BEGIN
IF INSERTING AND :NEW.woman_act IS NOT NULL THEN
v_id.extend;
v_ids(v_ids.last) := :NEW.v_ids;
END IF;
IF UPDATING AND (:NEW.woman_act IS NOT NULL AND :OLD.woman_act IS NULL) OR (:OLD.woman_act <> :NEW.woman_act) THEN
v_id.extend;
v_ids(v_ids.last) := :OLD.v_ids;
END IF;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR i IN 1..v_ids.LAST LOOP
INSERT INTO v_changes(
id,
person_id,
reg_number,
last_name,
first_name,
dob,
b_country,
cit_country,
poe,
is_woman_act
)
SELECT
v_changes_seq.nextval,
p.id, --personId
p.reg_number,
p.last_name,
p.first_name,
p.dob,
cc1.valid_code,
cc2.valid_code,
poe.valid_code,
(case woman_act when 'X' then 1 else 0 end)
FROM person p
LEFT JOIN country_code cc1 ON p.birth_c_id = cc1.id
LEFT JOIN country_code cc2 ON p.cit_country_id = cc2.id
LEFT JOIN loc_code poe ON p.poe_id = poe.id
END LOOP;
END AFTER STATEMENT;
END vawa_changes_trg;
这里似乎不需要使用复合触发器,因为不需要查询 person
table。只需使用行级触发器并在您的逻辑中引用 :new
和 :old
伪记录
create or replace trigger trg_biur_person
before insert or update on person
for each row
begin
IF :new.woman_act = 'X'
THEN
INSERT INTO v_changes(
id,
person_id,
reg_number,
last_name,
first_name,
dob,
b_country,
cit_country,
poe,
is_woman_act
)
SELECT
v_changes_seq.nextval,
:new.id, --personId
:new.reg_number,
:new.last_name,
:new.first_name,
:new.dob,
(select cc1.valid_code
from country_code cc1
where cc1.id = :new.birth_c_id),
(select cc2.valid_code
from country_code cc2
where cc2.id = :new.cit_country_id),
(select poe.valid_code
from loc_code poe
where poe.poe_id = :new.birth_c_id),
(case :new.woman_act when 'X' then 1 else 0 end)
from dual;
end if;
end;
假设您刚刚学习 PL/SQL,创建一些局部变量并在 insert
语句中使用它们可能更容易,即
create or replace trigger trg_biur_person
before insert or update on person
for each row
declare
l_b_country v_changes.b_country%type;
begin
begin
select cc1.valid_code
into l_b_country
from country_code cc1
where cc1.id = :new.birth_c_id;
exception
-- The fact that you're trying to do a `left join` makes me believe
-- that you want to allow someone to insert a row with a `birth_c_id`
-- that doesn't exist in the `country_code` table. That doesn't make
-- sense to me but that's what I'm going with. If that isn't a valid
-- use case, you can omit the exception handler
when no_data_found
then
l_b_country := null;
end;
...
insert into v_changes ...
values( ..., l_b_country, ... );
end;
我正在研究复合触发器,但我很难弄清楚如何让它发挥作用。触发器在 人 table 上。有一列woman_act。如果插入了一个新行并且该列不为空,那么我们需要将该行插入 v_changes table 或者如果该列是从 null 到 'X' 而不是将该行插入 v_changes table .使用 COMPOUND 触发器是因为我得到 变异 table 并且发生这种情况是因为我从 select.
插入这是逻辑
--Insert with person.woman_act == ‘ ’ do nothing
--Insert with person.woman_act == ‘X’ insert with is_vawa = 1/true
--Update with person.woman_act changed from ‘ ‘ to ‘X’ insert with is_woman_act = 1/true
create table person (
id number primary key,
reg_number varchar2(9),
last_name charchar2(255),
first_name charchar2(255),
dob date,
birth_c_id number(38,0),
cit_country_id number(38,0),
poe_id number(38,0),
woman_act varchar2(1) check (woman_act in (null, 'X'))
);
create table v_changes (
id number primary key,
person_id number not null,
reg_number varchar2(9),
last_name charchar2(255),
first_name charchar2(255),
dob date,
b_country varchar2(255),
cit_country varchar2(255),
poe varchar2(30),
is_woman_act number(1,0)
);
create table country_code (
id number primary key,
valid_code varchar2(255)
);
create table loc_code (
id number primary key,
valid_code varchar2(255)
);
这是我的触发器。非常感谢任何想法和建议。
CREATE OR REPLACE TRIGGER v_changes_trg
FOR INSERT OR UPDATE OF woman_act ON person
COMPOUND TRIGGER
TYPE t_vawa_type IS TABLE OF person.woman_act%TYPE;
t_vawa t_vawa_type := t_vawa_type();
TYPE t_v_id IS TABLE OF person.id%TYPE;
v_ids t_v_id :=t_v_id();
BEFORE STATEMENT IS
t_vawas := t_vawa_type();
v_ids :=t_v_id();
END BEFORE STATEMENT;
BEFORE EACH ROW IS
t_vawa_id person.id%ROWTYPE;
BEGIN
IF INSERTING AND :NEW.woman_act IS NOT NULL THEN
v_id.extend;
v_ids(v_ids.last) := :NEW.v_ids;
END IF;
IF UPDATING AND (:NEW.woman_act IS NOT NULL AND :OLD.woman_act IS NULL) OR (:OLD.woman_act <> :NEW.woman_act) THEN
v_id.extend;
v_ids(v_ids.last) := :OLD.v_ids;
END IF;
END BEFORE EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR i IN 1..v_ids.LAST LOOP
INSERT INTO v_changes(
id,
person_id,
reg_number,
last_name,
first_name,
dob,
b_country,
cit_country,
poe,
is_woman_act
)
SELECT
v_changes_seq.nextval,
p.id, --personId
p.reg_number,
p.last_name,
p.first_name,
p.dob,
cc1.valid_code,
cc2.valid_code,
poe.valid_code,
(case woman_act when 'X' then 1 else 0 end)
FROM person p
LEFT JOIN country_code cc1 ON p.birth_c_id = cc1.id
LEFT JOIN country_code cc2 ON p.cit_country_id = cc2.id
LEFT JOIN loc_code poe ON p.poe_id = poe.id
END LOOP;
END AFTER STATEMENT;
END vawa_changes_trg;
这里似乎不需要使用复合触发器,因为不需要查询 person
table。只需使用行级触发器并在您的逻辑中引用 :new
和 :old
伪记录
create or replace trigger trg_biur_person
before insert or update on person
for each row
begin
IF :new.woman_act = 'X'
THEN
INSERT INTO v_changes(
id,
person_id,
reg_number,
last_name,
first_name,
dob,
b_country,
cit_country,
poe,
is_woman_act
)
SELECT
v_changes_seq.nextval,
:new.id, --personId
:new.reg_number,
:new.last_name,
:new.first_name,
:new.dob,
(select cc1.valid_code
from country_code cc1
where cc1.id = :new.birth_c_id),
(select cc2.valid_code
from country_code cc2
where cc2.id = :new.cit_country_id),
(select poe.valid_code
from loc_code poe
where poe.poe_id = :new.birth_c_id),
(case :new.woman_act when 'X' then 1 else 0 end)
from dual;
end if;
end;
假设您刚刚学习 PL/SQL,创建一些局部变量并在 insert
语句中使用它们可能更容易,即
create or replace trigger trg_biur_person
before insert or update on person
for each row
declare
l_b_country v_changes.b_country%type;
begin
begin
select cc1.valid_code
into l_b_country
from country_code cc1
where cc1.id = :new.birth_c_id;
exception
-- The fact that you're trying to do a `left join` makes me believe
-- that you want to allow someone to insert a row with a `birth_c_id`
-- that doesn't exist in the `country_code` table. That doesn't make
-- sense to me but that's what I'm going with. If that isn't a valid
-- use case, you can omit the exception handler
when no_data_found
then
l_b_country := null;
end;
...
insert into v_changes ...
values( ..., l_b_country, ... );
end;