问题描述
建议我使用复合触发器,请找到要求和下面的代码。
1、如果是Delete ,则不能删除表中创建的任何记录。
如果试图从该表中删除记录,则会捕获到,请在“审计”表中创建一个条目。
2.如果INSERTING ,则必填字段为ID,LOGIN_USER
•在插入到表中之前,请验证不存在具有相同的LOGIN_USER的现有记录
且记录状态为True。
•如果此验证失败,则返回错误代码和指示失败的消息。
•当将记录插入到表中时,事件后触发器将触发更新下列内容
字段: ID ,包括序列、创建的当前日期/时间和操作“记录插入”
3、如果UPDING ,必填字段为ID,LOGIN_USER
•更新表中的记录时,将触发事件后触发器执行以下操作:
o在影响表中插入记录,复制字段的当前值。
o字段ID、STATUS、LOGIN_USER用给定值填充或覆盖
•将触发事件前触发器,并防止更新不活动的记录。
问题是:
1、在DELETE过程中,我得到了预期的错误,但没有在审计表中插入条目。
2.在INSERT过程中, fire_on_插入的值为TRUE。
3.在更新期间,当我更新时,它将无限期地运行qquery。
请建议最后的代码,因为我没有时间了。这是我第一次使用复合触发器。
创建或替换触发器CMP_TIG
用于删除、插入或更新ID、NUM、登录用户T1
复合触发器
类型t_DBLOGIN是T %RowTYPE ;的表
v_DBLOGON t_DBLOGIN := t_DBLOGIN() ;
I号: =0 ;
V_LOGIN_USER编号;
类型t_审核IS表的审核_TAB %OTYPE ;
v_审计t_审计:= t_审计() ;
j编号:=0 ;
之前语句为
开始
dbms_输出.put_line ('In before语句') ;
语句前结束;
每行之前为
开始
v_audit.extend(1000) ;
v_DBLOGON.extend(1000) ;
如果删除,则
DBMS_OUTPUT.PUT_line ('删除前') ;
j := j+1 ;
v_Audiit(j).ID :=审计_SEQ.NEXTVAL ;
v_Audit(j).操作:='记录删除';
v_审计(j).OBJECTS :='T1';
v_audit(j).IP_AddR := SYS_CONTEXT ('用户V','IP_地址') ;
v_audit(j).DB_LOGIN := SYS.LOGIN_USER ;
v_audit(j).OS_USER := SYS_CONTEXT ('用户V','OS_USER') ;
v_审计(j)。创建的:=系统日期;
结束IF; --关闭IF以便删除
如果插入,则
IF INSERT_FLAG.fire_on_插入='真',然后
从T1选择计数(1)到V_LOGIN_USER
其中: LOGIN_USER = :新.LOGIN_USER AND STAUTS='真';
如果(V_LOGIN_USER>=1) ,则
ALE_APPY_错误( -20002,'数据库登录用户已存在', TRUE ) ;
结束IF ;
I:=I+1 ;
v_DBLOGON(I).ID := DB_SEQ.NEXTVAL ;
v_DBLOGON(I)。创建: =SYSD ;
v_DBLOGON(I).CREED_BY :=用户;
v_DBLOGON(I).事件:='记录插入';
结束IF ;
结束如果; --关闭如果插入
如果正在更新,则
if :old.status ='非活动',然后
错误(-20002,'不能更新无效记录',真) ;
结束IF ;
I := I+1 ;
v_DBLOGON(I).ID := DB_SEQ.NEXTVAL ;
v_DBLOGON(I).STATUS :='False';
v_DBLOGON(I).LOGIN_USER :=:旧.LOGIN_USER ;
结束IF ;
每行前结束;
语句后为
开始
如果删除,则
forall 1..v_audit.count()中的J
插入到审计_TAB值v_Audit(J)中;
ASTED_APLY_错误(-20002,'DBLOGIN_USER_INFO表数据不能删除', TRUE ) ;
结束IF ;
如果插入,则
Forall I in 1..v_DBLOGON.count()
插入T1值v_DBLOGON(I) ;
结束IF ;
如果正在更新,则
INSERT_FLAG.fire_on_插入:='False';
对于1..v_DBLOGON.count()中的所有I
插入T1值v_DBLOGON(I) ;
INSERT_FLAG.fire_on_插入:='true';
结束IF ;
语句后结束;
CMP_TIG结束;
/
1、如果是Delete ,则不能删除表中创建的任何记录。
如果试图从该表中删除记录,则会捕获到,请在“审计”表中创建一个条目。
2.如果INSERTING ,则必填字段为ID,LOGIN_USER
•在插入到表中之前,请验证不存在具有相同的LOGIN_USER的现有记录
且记录状态为True。
•如果此验证失败,则返回错误代码和指示失败的消息。
•当将记录插入到表中时,事件后触发器将触发更新下列内容
字段: ID ,包括序列、创建的当前日期/时间和操作“记录插入”
3、如果UPDING ,必填字段为ID,LOGIN_USER
•更新表中的记录时,将触发事件后触发器执行以下操作:
o在影响表中插入记录,复制字段的当前值。
o字段ID、STATUS、LOGIN_USER用给定值填充或覆盖
•将触发事件前触发器,并防止更新不活动的记录。
问题是:
1、在DELETE过程中,我得到了预期的错误,但没有在审计表中插入条目。
2.在INSERT过程中, fire_on_插入的值为TRUE。
3.在更新期间,当我更新时,它将无限期地运行qquery。
请建议最后的代码,因为我没有时间了。这是我第一次使用复合触发器。
创建或替换触发器CMP_TIG
用于删除、插入或更新ID、NUM、登录用户T1
复合触发器
类型t_DBLOGIN是T %RowTYPE ;的表
v_DBLOGON t_DBLOGIN := t_DBLOGIN() ;
I号: =0 ;
V_LOGIN_USER编号;
类型t_审核IS表的审核_TAB %OTYPE ;
v_审计t_审计:= t_审计() ;
j编号:=0 ;
之前语句为
开始
dbms_输出.put_line ('In before语句') ;
语句前结束;
每行之前为
开始
v_audit.extend(1000) ;
v_DBLOGON.extend(1000) ;
如果删除,则
DBMS_OUTPUT.PUT_line ('删除前') ;
j := j+1 ;
v_Audiit(j).ID :=审计_SEQ.NEXTVAL ;
v_Audit(j).操作:='记录删除';
v_审计(j).OBJECTS :='T1';
v_audit(j).IP_AddR := SYS_CONTEXT ('用户V','IP_地址') ;
v_audit(j).DB_LOGIN := SYS.LOGIN_USER ;
v_audit(j).OS_USER := SYS_CONTEXT ('用户V','OS_USER') ;
v_审计(j)。创建的:=系统日期;
结束IF; --关闭IF以便删除
如果插入,则
IF INSERT_FLAG.fire_on_插入='真',然后
从T1选择计数(1)到V_LOGIN_USER
其中: LOGIN_USER = :新.LOGIN_USER AND STAUTS='真';
如果(V_LOGIN_USER>=1) ,则
ALE_APPY_错误( -20002,'数据库登录用户已存在', TRUE ) ;
结束IF ;
I:=I+1 ;
v_DBLOGON(I).ID := DB_SEQ.NEXTVAL ;
v_DBLOGON(I)。创建: =SYSD ;
v_DBLOGON(I).CREED_BY :=用户;
v_DBLOGON(I).事件:='记录插入';
结束IF ;
结束如果; --关闭如果插入
如果正在更新,则
if :old.status ='非活动',然后
错误(-20002,'不能更新无效记录',真) ;
结束IF ;
I := I+1 ;
v_DBLOGON(I).ID := DB_SEQ.NEXTVAL ;
v_DBLOGON(I).STATUS :='False';
v_DBLOGON(I).LOGIN_USER :=:旧.LOGIN_USER ;
结束IF ;
每行前结束;
语句后为
开始
如果删除,则
forall 1..v_audit.count()中的J
插入到审计_TAB值v_Audit(J)中;
ASTED_APLY_错误(-20002,'DBLOGIN_USER_INFO表数据不能删除', TRUE ) ;
结束IF ;
如果插入,则
Forall I in 1..v_DBLOGON.count()
插入T1值v_DBLOGON(I) ;
结束IF ;
如果正在更新,则
INSERT_FLAG.fire_on_插入:='False';
对于1..v_DBLOGON.count()中的所有I
插入T1值v_DBLOGON(I) ;
INSERT_FLAG.fire_on_插入:='true';
结束IF ;
语句后结束;
CMP_TIG结束;
/
专家解答
干得好-你已经很接近了。下面是我的代码,使用的是精简版本的表,但要求是相同的,即
插入=>填充其他列(已创建等)
更新=>保留上一行的副本
不允许删除=>,保留对尝试的审核
我给包添加了一个进程,用于处理自动的东西。
为您练习-确保在发生错误时重置标志,以便插入标志永远不会被错误地*打开。
插入=>填充其他列(已创建等)
更新=>保留上一行的副本
不允许删除=>,保留对尝试的审核
我给包添加了一个进程,用于处理自动的东西。
SQL> drop table t1 purge;
Table dropped.
SQL> create table t1 ( x int ,y int, created date, created_by varchar2(10));
Table created.
SQL>
SQL> drop table audit_tab purge;
Table dropped.
SQL> create table audit_tab ( action varchar2(10), who varchar2(20), dte date, x int ,y int);
Table created.
SQL>
SQL>
SQL> create or replace
2 package audit_pkg is
3 type t_dblogin is table of t1%rowtype index by pls_integer;
4 type t_audit is table of audit_tab%rowtype index by pls_integer;
5
6 fire_on_insert boolean := true;
7
8 procedure delete_separate_transaction(p_audit t_audit);
9 end;
10 /
Package created.
SQL>
SQL> create or replace
2 package body audit_pkg is
3 procedure delete_separate_transaction(p_audit t_audit) is
4 pragma autonomous_transaction;
5 begin
6
7 forall j in 1..p_audit.count()
8 insert into audit_tab values p_audit(j);
9 commit;
10 end;
11 end;
12 /
Package body created.
SQL>
SQL> create or replace trigger cmp_trig
2 for delete or insert or update on t1
3 compound trigger
4
5 v_dblogon audit_pkg.t_dblogin;
6 v_audit audit_pkg.t_audit;
7
8 before each row is
9 begin
10 if deleting then
11 v_audit(v_audit.count+1).action := 'delete';
12 v_audit(v_audit.count).who := user;
13 v_audit(v_audit.count).dte := sysdate;
14 v_audit(v_audit.count).x := :old.x;
15 v_audit(v_audit.count).y := :old.y;
16 end if; --close if for deleting
17
18 if inserting then
19 if audit_pkg.fire_on_insert then
20 :new.created :=sysdate;
21 :new.created_by := user;
22 end if;
23 end if; --close if for inserting
24
25 if updating then
26 v_dblogon(v_dblogon.count+1).x := :old.x;
27 v_dblogon(v_dblogon.count).y := :old.x;
28 v_dblogon(v_dblogon.count).created := :old.created;
29 v_dblogon(v_dblogon.count).created_by := :old.created_by;
30 end if;
31
32 end before each row;
33
34
35 after statement is
36 begin
37 if deleting then
38 audit_pkg.delete_separate_transaction(v_audit);
39 raise_application_error (-20002, 'dblogin_user_info table data can not be deleted', true);
40 end if;
41
42 if updating then
43 audit_pkg.fire_on_insert := false;
44 forall i in 1..v_dblogon.count()
45 insert into t1 values v_dblogon(i);
46 audit_pkg.fire_on_insert := true;
47 end if;
48 end after statement;
49
50 end cmp_trig;
51
52 /
Trigger created.
SQL> sho err
No errors.
SQL>
SQL>
SQL> insert into t1 ( x , y ) values (1,2);
1 row created.
SQL> select * from t1;
X Y CREATED CREATED_BY
---------- ---------- --------- ----------
1 2 21-NOV-16 MCDONAC
1 row selected.
SQL> select * from audit_tab;
no rows selected
SQL>
SQL> insert into t1 ( x , y ) values (3,4);
1 row created.
SQL> select * from t1;
X Y CREATED CREATED_BY
---------- ---------- --------- ----------
1 2 21-NOV-16 MCDONAC
3 4 21-NOV-16 MCDONAC
2 rows selected.
SQL> select * from audit_tab;
no rows selected
SQL>
SQL> update t1
2 set y = 5
3 where x = 1;
1 row updated.
SQL> select * from t1;
X Y CREATED CREATED_BY
---------- ---------- --------- ----------
1 5 21-NOV-16 MCDONAC
3 4 21-NOV-16 MCDONAC
1 1 21-NOV-16 MCDONAC
3 rows selected.
SQL> select * from audit_tab;
no rows selected
SQL>
SQL> delete from t1
2 where x = 3;
delete from t1
*
ERROR at line 1:
ORA-20002: dblogin_user_info table data can not be deleted
ORA-06512: at "MCDONAC.CMP_TRIG", line 37
ORA-04088: error during execution of trigger 'MCDONAC.CMP_TRIG'
SQL> select * from t1;
X Y CREATED CREATED_BY
---------- ---------- --------- ----------
1 5 21-NOV-16 MCDONAC
3 4 21-NOV-16 MCDONAC
1 1 21-NOV-16 MCDONAC
3 rows selected.
SQL> select * from audit_tab;
ACTION WHO DTE X Y
---------- -------------------- --------- ---------- ----------
delete MCDONAC 21-NOV-16 3 4
1 row selected.
SQL>
SQL>
为您练习-确保在发生错误时重置标志,以便插入标志永远不会被错误地*打开。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




