pl/sql 突变 table 更新
pl/sql mutation table on update
我知道,这个问题已经想了很多次了,但我需要你的建议:)
有 2 个 table:
- Sale_income
| item |income |create_user |create_date |last_update_user | update_time|
|------|-------|------------|-------------------|-----------------|------------|
| 1 | 100 |duck |05-19-2016 |human |05-19-2016 |
| 2 | 250 |dog |05-19-2016 |human |05-19-2016 |
| 3 | 210 |cat |05-20-2016 |human |05-19-2016 |
- Sale_income_audit
| item |change_id|last_inc|new_inc |user_update|update_date|operation |
|------|---------|--------|----------|-----------|-----------|------------|
| 1 | 1 |null |05-19-2016|duck |05-19-2016 |I |
| 2 | 2 |null |05-19-2016|dog |05-19-2016 |I |
| 3 | 33 |null |05-20-2016|cat |05-19-2016 |I |
任务是:当有人进行插入、更新或删除时,触发器必须将上面发生动作的记录插入table Sale_income_audit(操作类型 - 列“操作”)。同时必须更新 table
Sale_income(last_update_user 和 update_time)。
我是这样做的:创建包含 3 个变量的包:
create or replace package Sale_income_var as
v_old_income BINARY_INTEGER := null;
v_new_income BINARY_INTEGER := null;
v_item BINARY_INTEGER := null;
END Sale_income_var;
和 2 个触发器
第一
create or replace trigger audit_income_IUD
after insert or update or delete on Sale_income
for each row
begin
.
.
elsif updating then
Sale_income_var.v_old_income := :old.income;
Sale_income_var.v_new_income := :new.income;
if Sale_income_var.v_item is null then
Sale_income_var.v_item := :old.item;
DBMS_OUTPUT.PUT_LINE(Sale_income_var.v_item);
end if;
.
.
end if;
end audit_income_IUD;
秒
create or replace trigger sale_income_au
after update of income on Sale_income
begin
update Sale_income set last_update_user = user, last_update_date = sysdate
where item = Sale_income_var.v_item;
INSERT into Sale_income_audit (item,
change_id,
last_income,
new_income,
user_update,
update_date,
operation)
VALUES (Sale_income_var.v_item,
auto_incr.NEXTVAL,
Sale_income_var.v_old_income,
Sale_income_var.v_new_income,
user,
sysdate,
'U');
Sale_income_var.v_item := null;
end sale_income_au;
它起作用了,但我发现它是错误的解决方案。因为更新块从 'general' 触发器移动到另一个触发器并且这个带有变量的魔法不太好,我是对的?
你会如何决定这个任务,你会在我的解决方案中改变什么?
感谢您的帮助:)
答案看起来很简单。需要在每行 之后使用 并在块 'update'
中添加
:new.last_update_user := user;
:new.last_update_date := sysdate;
而且我们可以限制在一个没有包的触发器!
只需一个 BEFORE
触发器即可完成。
在触发器允许修改table列的NEW值之前,这些修改的值存储在table中,所以last_update_user
和update_time
列可以通过这种方式更新。
create or replace trigger audit_income_IUD
BEFORE insert or update or delete on Sale_income
for each row
declare
operation_type char;
begin
if updating or inserting then
:new.update_time := sysdate;
:new.last_update_user := user;
end if;
CASE
WHEN updating THEN operation_type := 'U';
WHEN inserting THEN operation_type := 'I';
WHEN deleting THEN operation_type := 'D';
END CASE;
INSERT into Sale_income_audit (item,
change_id,
last_income,
new_income,
user_update,
update_date,
operation)
VALUES (:old.item,
auto_incr.NEXTVAL,
:old.income,
:new.income,
user,
sysdate,
operation_type);
end;
/
我知道,这个问题已经想了很多次了,但我需要你的建议:)
有 2 个 table:
- Sale_income
| item |income |create_user |create_date |last_update_user | update_time|
|------|-------|------------|-------------------|-----------------|------------|
| 1 | 100 |duck |05-19-2016 |human |05-19-2016 |
| 2 | 250 |dog |05-19-2016 |human |05-19-2016 |
| 3 | 210 |cat |05-20-2016 |human |05-19-2016 |
- Sale_income_audit
| item |change_id|last_inc|new_inc |user_update|update_date|operation |
|------|---------|--------|----------|-----------|-----------|------------|
| 1 | 1 |null |05-19-2016|duck |05-19-2016 |I |
| 2 | 2 |null |05-19-2016|dog |05-19-2016 |I |
| 3 | 33 |null |05-20-2016|cat |05-19-2016 |I |
任务是:当有人进行插入、更新或删除时,触发器必须将上面发生动作的记录插入table Sale_income_audit(操作类型 - 列“操作”)。同时必须更新 table Sale_income(last_update_user 和 update_time)。 我是这样做的:创建包含 3 个变量的包:
create or replace package Sale_income_var as
v_old_income BINARY_INTEGER := null;
v_new_income BINARY_INTEGER := null;
v_item BINARY_INTEGER := null;
END Sale_income_var;
和 2 个触发器
第一
create or replace trigger audit_income_IUD
after insert or update or delete on Sale_income
for each row
begin
.
.
elsif updating then
Sale_income_var.v_old_income := :old.income;
Sale_income_var.v_new_income := :new.income;
if Sale_income_var.v_item is null then
Sale_income_var.v_item := :old.item;
DBMS_OUTPUT.PUT_LINE(Sale_income_var.v_item);
end if;
.
.
end if;
end audit_income_IUD;
秒
create or replace trigger sale_income_au
after update of income on Sale_income
begin
update Sale_income set last_update_user = user, last_update_date = sysdate
where item = Sale_income_var.v_item;
INSERT into Sale_income_audit (item,
change_id,
last_income,
new_income,
user_update,
update_date,
operation)
VALUES (Sale_income_var.v_item,
auto_incr.NEXTVAL,
Sale_income_var.v_old_income,
Sale_income_var.v_new_income,
user,
sysdate,
'U');
Sale_income_var.v_item := null;
end sale_income_au;
它起作用了,但我发现它是错误的解决方案。因为更新块从 'general' 触发器移动到另一个触发器并且这个带有变量的魔法不太好,我是对的?
你会如何决定这个任务,你会在我的解决方案中改变什么? 感谢您的帮助:)
答案看起来很简单。需要在每行 之后使用 并在块 'update'
中添加 :new.last_update_user := user;
:new.last_update_date := sysdate;
而且我们可以限制在一个没有包的触发器!
只需一个 BEFORE
触发器即可完成。
在触发器允许修改table列的NEW值之前,这些修改的值存储在table中,所以last_update_user
和update_time
列可以通过这种方式更新。
create or replace trigger audit_income_IUD
BEFORE insert or update or delete on Sale_income
for each row
declare
operation_type char;
begin
if updating or inserting then
:new.update_time := sysdate;
:new.last_update_user := user;
end if;
CASE
WHEN updating THEN operation_type := 'U';
WHEN inserting THEN operation_type := 'I';
WHEN deleting THEN operation_type := 'D';
END CASE;
INSERT into Sale_income_audit (item,
change_id,
last_income,
new_income,
user_update,
update_date,
operation)
VALUES (:old.item,
auto_incr.NEXTVAL,
:old.income,
:new.income,
user,
sysdate,
operation_type);
end;
/