Home  >  Article  >  Database  >  oracle trigger代码

oracle trigger代码

WBOY
WBOYOriginal
2016-06-07 15:38:041158browse

sql 代码 --[6]// Oracle Trigger -- 实例 1------------------------ -- 创建触发器,当用户对 test 表执行 DML 语句时,将相关信息记录到日志表 -- 创建测试表 CREATE TABLE test ( t_id NUMBER(4), t_name VARCHAR2(20), t_age NUMBER(2), t_sex CHAR );

sql 代码

  1. --[6]// Oracle Trigger

  2. --实例1------------------------

  3. --创建触发器,当用户对test表执行DML语句时,将相关信息记录到日志表

  4. --创建测试表

  5. CREATE TABLE test

  6. (

  7. t_id NUMBER(4),

  8. t_name VARCHAR2(20),

  9. t_age NUMBER(2),

  10. t_sex CHAR

  11. );

  12. --创建记录测试表

  13. CREATE TABLE test_log

  14. (

  15. l_user VARCHAR2(15),

  16. l_type VARCHAR2(15),

  17. l_date VARCHAR2(30)

  18. );

  19. --创建触发器

  20. CREATE OR REPLACE TRIGGER test_trigger

  21. AFTER DELETE OR INSERT OR UPDATE ON test

  22. DECLARE

  23. v_type test_log.l_type%TYPE;

  24. BEGIN

  25. IF INSERTING THEN --INSERT触发

  26. v_type := 'INSERT';

  27. DBMS_OUTPUT.PUT_LINE('记录已经成功插入,并已记录到日志');

  28. ELSIF UPDATING THEN --UPDATE触发

  29. v_type := 'UPDATE';

  30. DBMS_OUTPUT.PUT_LINE('记录已经成功更新,并已记录到日志');

  31. ELSIF DELETING THEN

  32. v_type := 'DELETE';

  33. DBMS_OUTPUT.PUT_LINE('记录已经成功删除,并已记录到日志');

  34. END IF;

  35. INSERT INTO test_log VALUES(user,v_type,

  36. TO_CHAR(sysdate,'yyyy-mm-dd hh24:mi:ss'));

  37. END;

  38. /

  39. --下面我们来分别执行DML语句

  40. INSERT INTO test VALUES(101,'zhao',22,'M');

  41. UPDATE test SET t_age = 30 WHERE t_id = 101;

  42. DELETE test WHERE t_id = 101;

  43. --然后查看效果

  44. SELECT * FROM test;

  45. SELECT * FROM test_log;

  46.  

  47. --实例2------------------------

  48. --创建触发器,它将映射emp表中每个部门的总人数和总工资

  49. --创建映射表

  50. CREATE TABLE dept_sal

  51. AS

  52. SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno;

  53. DESC dept_sal;

  54. --创建触发器

  55. CREATE OR REPLACE TRIGGER emp_info

  56. AFTER INSERT OR UPDATE OR DELETE ON emp

  57. DECLARE

  58. CURSOR cur_emp IS

  59. SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno;

  60. BEGIN

  61. DELETE dept_sal; --触发时首先删除映射表信息

  62. FOR v_emp IN cur_emp LOOP

  63. --DBMS_OUTPUT.PUT_LINE(v_emp.deptno || v_emp.total_emp || v_emp.total_sal);

  64. --插入数据

  65. INSERT INTO dept_sal

  66. VALUES(v_emp.deptno,v_emp.total_emp,v_emp.total_sal);

  67. END LOOP;

  68. END;

  69. /

  70. --emp表进行DML操作

  71. INSERT INTO emp(empno,deptno,sal) VALUES('123','10',10000);

  72. SELECT * FROM dept_sal;

  73. DELETE EMP WHERE empno=123;

  74. SELECT * FROM dept_sal;

  75.  

  76. --实例3------------------------

  77. --创建触发器,它记录表的删除数据

  78. --创建表

  79. CREATE TABLE employee

  80. (

  81. id VARCHAR2(4) NOT NULL,

  82. name VARCHAR2(15) NOT NULL,

  83. age NUMBER(2) NOT NULL,

  84. sex CHAR NOT NULL

  85. );

  86. DESC employee;

  87. --插入数据

  88. INSERT INTO employee VALUES('e101','zhao',23,'M');

  89. INSERT INTO employee VALUES('e102','jian',21,'F');

  90. --创建记录表

  91. CREATE TABLE old_employee AS

  92. SELECT * FROM employee;

  93. DESC old_employee;

  94. --创建触发器

  95. CREATE OR REPLACE TRIGGER tig_old_emp

  96. AFTER DELETE ON employee --

  97. FOR EACH ROW --语句级触发,即每一行触发一次

  98. BEGIN

  99. INSERT INTO old_employee

  100. VALUES(:old.id,:old.name,:old.age,:old.sex); --:old代表旧值

  101. END;

  102. /

  103. --下面进行测试

  104. DELETE employee;

  105. SELECT * FROM old_employee;

  106.  

  107. --实例4------------------------

  108. --创建触发器,利用视图插入数据

  109. --创建表

  110. CREATE TABLE tab1 (tid NUMBER(4) PRIMARY KEY,tname VARCHAR2(20),tage NUMBER(2));

  111. CREATE TABLE tab2 (tid NUMBER(4),ttel VARCHAR2(15),tadr VARCHAR2(30));

  112. --插入数据

  113. INSERT INTO tab1 VALUES(101,'zhao',22);

  114. INSERT INTO tab1 VALUES(102,'yang',20);

  115. INSERT INTO tab2 VALUES(101,'13761512841','AnHuiSuZhou');

  116. INSERT INTO tab2 VALUES(102,'13563258514','AnHuiSuZhou');

  117. --创建视图连接两张表

  118. CREATE VIEW tab_view AS

  119. SELECT tab1.tid,tname,ttel,tadr FROM tab1,tab2

  120. WHERE tab1.tid = tab2.tid;

  121. --创建触发器

  122. CREATE OR REPLACE TRIGGER tab_trigger

  123. INSTEAD OF INSERT ON tab_view

  124. BEGIN

  125. INSERT INTO tab1(tid,tname) VALUES(:new.tid,:new.tname);

  126. INSERT INTO tab2(ttel,tadr) VALUES(:new.ttel,:new.tadr);

  127. END;

  128. /

  129. --现在就可以利用视图插入数据

  130. INSERT INTO tab_view VALUES(105,'zhaoyang','13886681288','beijing');

  131. --查看效果

  132. SELECT * FROM tab_view;

  133.  

  134. --实例5------------------------

  135. --创建触发器,比较emp表中更新的工资

  136. CREATE OR REPLACE TRIGGER sal_emp

  137. BEFORE UPDATE ON emp

  138. FOR EACH ROW

  139. BEGIN

  140.  

  141. IF :OLD.sal > :NEW.sal THEN

  142. DBMS_OUTPUT.PUT_LINE('工资减少');

  143. ELSIF :OLD.sal
  144. DBMS_OUTPUT.PUT_LINE('工资增加');

  145. ELSE

  146. DBMS_OUTPUT.PUT_LINE('工资未作任何变动');

  147. END IF;

  148. DBMS_OUTPUT.PUT_LINE('更新前工资 :' || :OLD.sal);

  149. DBMS_OUTPUT.PUT_LINE('更新后工资 :' || :NEW.sal);

  150. END;

  151. /

  152. --执行UPDATE查看效果

  153. UPDATE emp SET sal = 3000 WHERE empno = '7788';

  154.  

  155. --实例6------------------------

  156. --创建触发器,将操作CREATEDROP存储在log_info

  157. --创建表

  158. CREATE TABLE log_info

  159. (

  160. manager_user VARCHAR2(15),

  161. manager_date VARCHAR2(15),

  162. manager_type VARCHAR2(15),

  163. obj_name VARCHAR2(15),

  164. obj_type VARCHAR2(15)

  165. );

  166. --创建触发器

  167. CREATE OR REPLACE TRIGGER trig_log_info

  168. AFTER CREATE OR DROP ON SCHEMA

  169. BEGIN

  170. INSERT INTO log_info

  171. VALUES(USER,SYSDATE,SYS.DICTIONARY_OBJ_NAME,SYS.DICTIONARY_OBJ_OWNER,

  172. SYS.DICTIONARY_OBJ_TYPE);

  173. END;

  174. /

  175. --测试语句

  176. CREATE TABLE a(id NUMBER);

  177. CREATE TYPE aa AS OBJECT(id NUMBER);

  178. /

  179. DROP TABLE a;

  180. DROP TYPE aa;

  181. --查看效果

  182. SELECT * FROM log_info;

  183.  

  184. --相关数据字典-----------------------------------------------------//

  185. SELECT * FROM USER_TRIGGERS;

  186. SELECT * FROM ALL_TRIGGERS;

  187. SELECT * FROM DBA_TRIGGERS; --必须以DBA身份登陆才能使用此数据字典

  188.  

  189. --启用和禁用

  190. ALTER TRIGGER trigger_name DISABLE;

  191. ALTER TRIGGER trigger_name ENABLE;

  192. ------------------------------------------------------------------------------------------End//


 关于在 oracle trigger(insert)事件中调用存储过程的问题     

 最近用ORACLE触发器写了点东西,不过,确发现 ORA-04092ora-06512 等错误。怎么办?

最初,我也被弄得手忙脚乱。

于是,我查看 ORA-04092 提示的错误信息,是ROLLBACK和COMMIT 命令不能出现在触发器中。

于是,开始解决问题。发现,当在触发器里加入事务性操作时,会有如下错误:ORA-04092 cannot string in a trigger. 解决办法,在触发器里加入声明PRAGMA AUTONOMOUS_TRANSACTION,好了,不在弹出错误信息。

可是,我通过触发器调用存储过程,却发现存储过程执行后,数据没任何变化(我的存储过程是执行一次,删除一次中间表数据。)。难道是我的存储过程出了问题?单步调试,没任何问题。执行结果正确。

通过多次测试,发现原来是触发触发器的时候(触发事件为 insert after)由于没有提交(COMMIT)数据。在中间表中就查不到任何数据。处理方法,

第一步、新建一个中间表,做为触发器触发事件发生的中间表。

第二步、在中间表插入数据,提交。

第三步、在第一步新建的中间表中插入数据,提交执行成功。

第四步、检查结果,正常。


 能否在表的触发器中当一记录变化修改另一记录  

SQL> create or replace trigger addnum
  2  before update on test1.test1
  3  for each row
  4  begin
  5  update test1 set group1=(:new.group1+1) where group1=2;
  6  end;
  7  /

触发器已创建

已用时间:  00: 00: 00.00
SQL> update test1 set group1=7 where group1=1;
update test1 set group1=7 where group1=1
       *
ERROR
位于第 1
:
ORA-04091:
TEST1.TEST1 发生了变化,触发器/函数不能读

ORA-06512:
"TEST1.ADDNUM", line 2
ORA-04088:
触发器 'TEST1.ADDNUM' 执行过程中出错

 
这样是肯定不行的,因为触发器会引起死循环。用表层触发器,但表层是不能用:new:old 


SQL> create or replace procedure test3(i number,m number)
  2  as
  3  a number;
  4  str char(1000);
  5  begin
  6  update test1 set group1=i where group1=m;
  7  execute immediate 'COMMIT';
  8  a:=i;
  9  for a in i..m loop
 10  update test1 set group1=i+1 where group1=i;
 11  execute immediate 'COMMIT';
 12  end loop;
 13  end test3;
 14  /

过程已创建。

已用时间:  00: 00: 00.00
SQL> exec test3(2,4);
BEGIN test3(2,4); END;

*
ERROR
位于第 1
:
ORA-04091:
TEST1.TEST1 发生了变化,触发器/函数不能读

ORA-06512:
"TEST1.ADDNUM", line 2
ORA-04088:
触发器 'TEST1.ADDNUM' 执行过程中出错

ORA-06512:
"TEST1.TEST3", line 6
ORA-06512:
line 1

 
 


1
、使用视图或者临时表

You can do:
  1. Rename your table with another name;
  2. Create a view for select * from the table with the original name of the table;
  3. Create a instead of trigger on the view, in the view you can access and update yur base

table.


Example of instead of trigger for this case:

[ Code Start ]
create table t1(
  id        number(6)    primary key
 ,pid       number(6)
 ,value     number(15,2)
 ,f1        varchar2(10)
 ,f2        varchar2(20)
);


create or replace view t1_v as select * from t1;

create or replace trigger bug_t1_v
instead of update on t1_v
for each row
declare
  procedure update_parents(i_id in number, i_value in number);
  procedure update_parents(i_id in number, i_value in number) is
  begin
    declare
      l_pid t1.pid%type;
    begin
      select pid into l_pid
        from t1
       where id = i_id;
      if l_pid 0 then 
        update t1 set value = nvl(value,0) + nvl(i_value,0)
         where id = l_pid;
        update_parents(l_pid, i_value);
      end if;
    exception
      when no_data_found then
        null; 
    end;       
  end update_parents;
begin
  --
  -- Update Value Field for current record and Parent records 
  --
  if nvl(:new.value,0) - nvl(:old.value,0) 0 then
     update t1 set value = value + nvl(:new.value,0) - nvl(:old.value,0)
      where id = :new.id;
     update_parents(:new.id, nvl(:new.value,0) - nvl(:old.value,0)); 
  end if;
  --
  -- Update Others Fields
  --
  update t1 set f1 = :new.f1
               ,f2 = :new.f2
   where id = :new.id;
end;
 
--
-- Testing
--
-- With this view: t1_v
--
begin
  for i in 1..50 loop
    Insert into t1_v values(i, i-1, 0, '', '');
  end loop;
end;
/

delete from t1_v;

begin
  for i in 1..50 loop
    Insert into t1_v values(i, i-1, 0, '', '');
  end loop;
end;
/

update t1_v set f1 = 'TEST' where id = 49;


update t1_v set value = value + 5 , f1 = 'AA', F2 = 'BB'
where id = 50;


[ Code End ]

使用临时表

11:04:36 SQL> CREATE GLOBAL TEMPORARY TABLE Tmp(
11:04:39   2  rid varchar2(20))ON COMMIT DELETE ROWS;

表已创建。

已用时间:  00: 00: 00.16
11:07:30 SQL> create or replace trigger trg_tb
11:07:36   2  after insert on tb
11:07:36   3  for each row
11:07:36   4  begin
11:07:36   5  if :new.col2='laji' then
11:07:36   6   insert into tmp values(:new.rowid);
11:07:36   7  end if;
11:07:36   8  end trg_tb;
11:07:36   9  /

触发器已创建

已用时间:  00: 00: 00.47
11:07:36 SQL> create or replace trigger trg_tb_del
11:07:44   2  after insert on tb
11:07:46   3  begin
11:07:46   4  delete from tb where exists(select 1 from tmp where rid=tb.rowid);
11:07:46   5  end trg_tb_del;
11:07:46   6  /

触发器已创建

已用时间:  00: 00: 00.31
11:08:59 SQL> select count(1) from tb;

  COUNT(1)
----------
        22

已用时间:  00: 00: 00.00
11:09:08 SQL> insert into tb(col1,col2) values('aaa','laji');

已创建 1 行。

已用时间:  00: 00: 00.00
11:09:12 SQL> select count(1) from tb;

  COUNT(1)
----------
        22

已用时间:  00: 00: 00.16
11:09:14 SQL>

From Metalink

Problem Description -------------------
Oracle does not allow you to read a mutating table in a row trigger because if you can read it,

the information may be incorrect (not read consistent). If you attempt this, the following error

is returned:
ORA-04091
Table %s.%s is mutating, trigger/function may not see it
However, you can perform this operation in a statement trigger.
One way to handle this situation is to use a package PL/SQL table to store ROWIDs of updated

records in a row trigger, and reprocess the updated
 records in a statement trigger.
Below is an example.

 Important Note --------------
Note that there are concurrency issues with this if more than one session tries to perform

operations simultaneously.
This is not intended as a total solution, but as the framework to help show one option.
 Example Workaround ------------------
[code:1:50147eb56b]
create or replace package emp_pkg as
type
emp_tab_type is table of rowid index by binary_integer;
emp_tab
 emp_tab_type;
emp_index binary_integer;
 end emp_pkg;
 /
create or replace trigger emp_bef_stm_all
 before insert or update or delete on emp
 begin
/*
Remember to reset the pl/sql table before each statement
*/
emp_pkg.emp_index := 0;
 end;
 /
create or replace trigger emp_aft_row_all
 after insert or update or delete on emp
 for each row
 begin
/*
Store the rowid of updated record into global pl/sql table
*/
emp_pkg.emp_index := emp_pkg.emp_index + 1;
emp_pkg.emp_tab(emp_pkg.emp_index) := :new.rowid;
 end;
 /


create or replace trigger emp_aft_stm_all
 after
insert or update or delete on emp
 begin
for i in 1 .. emp_pkg.emp_index loop
 /*

 Re-process the updated records.
 There is no restriction here.
 */
 dbms_output.put_line(emp_pkg.emp_tab(i));
end loop;
emp_pkg.emp_index := 0;
 end;
 /
怎么样把提交的数据通过触发器进行验证,如果不合条件,直接删除?

楼主andywzw()2004-09-30 11:04:40 Oracle / 开发提问

在应用程序中,有些数据是垃圾数据,现在程序在前段提交的时候没有验证机制,补做代价比较大,我现在想能不能在后台oracle通过触发器,对插入动作进行验证,如果发现垃圾数据,直接删除,这样比做存储过程进行定时监控要减少系统资源的占用,但是我不知道如何实现,请高手指教!问题点数:100、回复次数:32Top

1 drabitsquare回复于 2004-09-30 11:14:23 得分 0

这样做违反事务的一致性要求,oracle不会提供这种手段的。一次插入的数据要么都插入,要么都不插入。Top

2 bluelambbluelamb回复于 2004-09-30 11:18:48 得分 0

只能够在提交前验证Top

3 bzszpSongZip回复于 2004-09-30 11:19:44 得分100

使用临时表  
   
  11:04:36   SQL>   CREATE   GLOBAL   TEMPORARY   TABLE   Tmp(  
  11:04:39       2     rid   varchar2(20))ON   COMMIT   DELETE   ROWS;  
   
 
表已创建。  
   
 
已用时间:     00:   00:   00.16  
  11:07:30   SQL>   create   or   replace   trigger   trg_tb    
  11:07:36       2     after   insert   on   tb  
  11:07:36       3     for   each   row  
  11:07:36       4     begin  
  11:07:36       5     if   :new.col2='laji'   then  
  11:07:36       6       insert   into   tmp   values(:new.rowid);  
  11:07:36       7     end   if;  
  11:07:36       8     end   trg_tb;  
  11:07:36       9     /  
   
 
触发器已创建  
   
 
已用时间:     00:   00:   00.47  
  11:07:36   SQL>   create   or   replace   trigger   trg_tb_del  
  11:07:44       2     after   insert   on   tb  
  11:07:46       3     begin  
  11:07:46       4     delete   from   tb   where   exists(select   1   from   tmp   where   rid=tb.rowid);  
  11:07:46       5     end   trg_tb_del;  
  11:07:46       6     /  
   
 
触发器已创建  
   
 
已用时间:     00:   00:   00.31  
  11:08:59   SQL>   select   count(1)   from   tb;  
   
      COUNT(1)  
  ----------  
                  22  
   
 
已用时间:     00:   00:   00.00  
  11:09:08   SQL>   insert   into   tb(col1,col2)   values('aaa','laji');  
   
 
已创建   1   行。  
   
 
已用时间:     00:   00:   00.00  
  11:09:12   SQL>   select   count(1)   from   tb;  
   
      COUNT(1)  
  ----------  
                  22  
   
 
已用时间:     00:   00:   00.16  
  11:09:14   SQL>    
   
 
说明刚才插入的数据已经被删除掉了。Top

4 andywzw()回复于 2004-09-30 11:20:15 得分 0

实际上我的想法是这样的,先让它插入目标表,同时触发检查这个刚才插入的语句是否符合条件,如果不符合就从目标表中直接删除,如果符合,就不做任何操作。Top

5 bzszpSongZip回复于 2004-09-30 11:21:37 得分 0

通过一个行级触发器+一个表级触发器+临时表解决。Top

6 andywzw()回复于 2004-09-30 11:25:09 得分 0

那我不用再改写前台的应用程序了吗?前台的插入是通过java实现的,临时表是否影响正是数据的插入?Top

7 andywzw()回复于 2004-09-30 11:28:35 得分 0

bzszp(SongZip)   的方案都是很专业的,我太佩服了!我做个实验看结果!Top

8 bzszpSongZip回复于 2004-09-30 11:31:19 得分 0

不会的,用ON     COMMIT     DELETE     ROWS;   方式创建临时表,在会话  
  commit
以后oracle自动清空数据。  
     
  Top

9 andywzw()回复于 2004-09-30 11:38:26 得分 0

对了,你的临时表只有一个字段啊,能满足我对多个字段的验证吗?Top

10 bzszpSongZip回复于 2004-09-30 11:41:33 得分 0

没有问题,这个是存放的rowid,对于每一行数据都是唯一的。  
 
判断是在行级触发器内部判断,如果是垃圾数据  
 
纪录:new.rowid到临时表  
 
在表级触发器里面集中进行删除。Top

11 andywzw()回复于 2004-09-30 11:44:18 得分 0

我觉得这样的方式比我们昨天讨论的解决问题的方案更好吧。这样可以避免不断的执行存储过程导致系统性能有影响。Top

12 drabitsquare回复于 2004-09-30 12:10:08 得分 0

studyTop

13 fightintokyo()回复于 2004-09-30 13:11:24 得分 0

bzszp(SongZip)good  
   
 
请教一个初级的问题。上面的解决方案中,行级触发器会确保在表级触发器前被触发么?(对触发器不太了解)Top

14 zhaokeke2004(男人·海洋)回复于 2004-09-30 13:27:06 得分 0

学习Top

15 bzszpSongZip回复于 2004-09-30 13:34:32 得分 0

tofightintokyo(黑龙)    
 
是的  
   
 
性能方面应该会好一些吧。  
 
毕竟直接通过rowid进行删除,而且是在commit之前就删除了  
 
这样那些不需要的数据就没有写回数据文件。Top

16 andywzw()回复于 2004-09-30 13:34:53 得分 0

bzszp(SongZip),请把你的tb表,desc   tb   给我看,我怎么做不下去了!Top

17 andywzw()回复于 2004-09-30 13:39:25 得分 0

bzszp(SongZip),是个专家级的人物,解决问题准确,耐心,细致,大家向他致敬!!!Top

18 fightintokyo()回复于 2004-09-30 13:56:51 得分 0

谢谢bzszp(SongZip)  
   
 
查了一下资料,果然触发器是按照以下顺序执行的。  
  1.
执行before表级触发器。  
  2.
以受影响的行进行循环。  
      a.
执行before行级触发器。(commit为止该行被lock  
      b.
执行after行级触发器。  
  3.
目标表定义的整合性check  
  4.
执行after表级触发器。  
   
 
再请教一个问题。  
 
为什么不在行级触发器中直接把不符合条件的数据delete了呢?  
 
这样就不需要临时表和行级触发器了亚。Top

19 andywzw()回复于 2004-09-30 14:00:30 得分 0

bzszp(SongZip),请把你的tb表,desc   tb   给我看,我怎么做不下去了!Top

20 bzszpSongZip回复于 2004-09-30 14:01:30 得分 0

这样会有问题的,行级触发器对于正在处理的表数据有操作限制。Top

21 bzszpSongZip回复于 2004-09-30 14:01:52 得分 0

13:50:23   SQL>   desc   tb;  
   
名称                                                                             ?             类型  
    -----------------------------------------   --------   --------------  
    COL1                                                                                               VARCHAR2(10)  
    COL2                                                                                               VARCHAR2(30)  
    COLNEW                                                                                           VARCHAR2(20)  
   
  13:52:32   SQL>Top

22 andywzw()回复于 2004-09-30 14:17:20 得分 0

bzszp(SongZip)     这办法绝对很棒,但是问题是  
    create   or   replace   trigger   trg_tb    
  after   insert   on   tb   for   each   row  
  begin  
  if   :new.col2='laji'   then  
    insert   into   tmp   values(:new.rowid);  
  end   if;  
  end   trg_tb;  
  /  
 
这个里面的你现在指定了col2,我要指定多列是不是用    
  if   :new.col2='laji'   or   :new.col1='xxx'   or     :new.coln='nnn'     then  
 
另外,这里的=后面的值是唯一的有局限性,我怎么从一个表,例如bad_word里面获得这些值?Top

23 andywzw()回复于 2004-09-30 14:23:43 得分 0

SQL>   desc   bad_word  
   
名称                                                                             ?             类型  
    -----------------------------------------   --------   -------------  
    ID                                                                                                   NUMBER(10)  
    KEY_WORD                                                                                       VARCHAR2(60)Top

24 bzszpSongZip回复于 2004-09-30 14:27:22 得分 0

select   判断,另外声明一个v_num   number的变量。  
  select   count(*)   into   v_num   from   bad_word    
  where   bad_word.colname=:new.col1;  
  if   v_num>0   then   --
属于包含垃圾信息的行  
      ...  
  end   if;Top

25 bzszpSongZip回复于 2004-09-30 14:28:25 得分 0

select   count(*)   into   v_num   from   bad_word    
  where   key_word=:new.col1;Top

26 andywzw()回复于 2004-09-30 14:58:01 得分 0

不好意思,我不知道怎么申明v_num   这个变量   :)Top

27 bzszpSongZip回复于 2004-09-30 15:02:09 得分 0

如:  
  create     or     replace     trigger     trg_tb          
  after     insert     on     tb     for     each     row  
  declare                     --
声明变量开始    
  v_num   number;     --
声明number类型的变量v_num  
  begin        
  ...  
  Top

28 andywzw()回复于 2004-09-30 15:23:44 得分 0

bzszp(SongZip)   我试验成功了!再问一下您,如果这种办法用于留言版后台过滤程序是不是很有价值的?比在前台更加主动,减少维护量。Top

29 bzszpSongZip回复于 2004-09-30 15:28:50 得分 0

减少了前台的工作量  
 
但是增加了后台的工作量  
 
这个根据实际情况来定吧。Top

30 andywzw()回复于 2004-09-30 16:32:34 得分 0

谢谢,结分,祝bzszp(SongZip)   及其各位国庆节愉快!Top

31 andywzw()回复于 2004-09-30 18:13:13 得分 0

create   or   replace   trigger   TRG_LEAVE_WORD  
  after   insert   on   LEAVE_WORD   for   each   row  
  declare    
  v_num   number;  
  begin  
  select   count(*)   into   v_num   from   bad_word    
  where   key_word   like   '%'||:new.TITLE||'%'   or   key_word   like   '%'||:new.CONTENT||'%';  
  if   v_num>0   then      
    insert   into   tmp   values(:new.rowid);  
  end   if;  
  end   TRG_LEAVE_WORD;  
  /  
   
 
这个触发器还是有问题的,过滤了CONTENT但不能过滤TITLE   ,如何解决,难道我的   or条件有问题?Top

32 andywzw()回复于 2004-10-01 02:02:28 得分 0

我找到解决的办法了,改写成如下样子完全可以使用:  
  create   or   replace   trigger   TRG_LEAVE_WORD  
  after   insert   on   LEAVE_WORD   for   each   row  
  declare    
  v_num   number;  
  begin  
    select   count(*)   into   v_num   from   BAD_WORD    
      where   instr(:new.TITLE,KEY_WORD)>0   or   instr(:new.CONTENT,KEY_WORD)>0;  
    if   v_num>0   then      
      insert   into   tmp   values(:new.rowid);  
    end   if;  
  end   TRG_LEAVE_WORD;  

 

 

 

 

 
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn