찾다

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;  

 

 

 

 

 
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL은 sqlite와 어떻게 다릅니 까?MySQL은 sqlite와 어떻게 다릅니 까?Apr 24, 2025 am 12:12 AM

MySQL과 Sqlite의 주요 차이점은 설계 개념 및 사용 시나리오입니다. 1. MySQL은 대규모 응용 프로그램 및 엔터프라이즈 수준의 솔루션에 적합하며 고성능 및 동시성을 지원합니다. 2. SQLITE는 모바일 애플리케이션 및 데스크탑 소프트웨어에 적합하며 가볍고 내부질이 쉽습니다.

MySQL의 색인이란 무엇이며 성능을 어떻게 향상 시키는가?MySQL의 색인이란 무엇이며 성능을 어떻게 향상 시키는가?Apr 24, 2025 am 12:09 AM

MySQL의 인덱스는 데이터 검색 속도를 높이는 데 사용되는 데이터베이스 테이블에서 하나 이상의 열의 주문 구조입니다. 1) 인덱스는 스캔 한 데이터의 양을 줄임으로써 쿼리 속도를 향상시킵니다. 2) B-Tree Index는 균형 잡힌 트리 구조를 사용하여 범위 쿼리 및 정렬에 적합합니다. 3) CreateIndex 문을 사용하여 CreateIndexIdx_customer_idonorders (customer_id)와 같은 인덱스를 작성하십시오. 4) Composite Indexes는 CreateIndexIdx_customer_orderOders (Customer_id, Order_Date)와 같은 다중 열 쿼리를 최적화 할 수 있습니다. 5) 설명을 사용하여 쿼리 계획을 분석하고 피하십시오

MySQL에서 트랜잭션을 사용하여 데이터 일관성을 보장하는 방법을 설명하십시오.MySQL에서 트랜잭션을 사용하여 데이터 일관성을 보장하는 방법을 설명하십시오.Apr 24, 2025 am 12:09 AM

MySQL에서 트랜잭션을 사용하면 데이터 일관성이 보장됩니다. 1) STARTTRANSACTION을 통해 트랜잭션을 시작한 다음 SQL 작업을 실행하고 커밋 또는 롤백으로 제출하십시오. 2) SavePoint를 사용하여 부분 롤백을 허용하는 저장 지점을 설정하십시오. 3) 성능 최적화 제안에는 트랜잭션 시간 단축, 대규모 쿼리 방지 및 격리 수준을 합리적으로 사용하는 것이 포함됩니다.

MySQL을 통해 어떤 시나리오에서 PostgreSQL을 선택할 수 있습니까?MySQL을 통해 어떤 시나리오에서 PostgreSQL을 선택할 수 있습니까?Apr 24, 2025 am 12:07 AM

MySQL 대신 PostgreSQL을 선택한 시나리오에는 다음이 포함됩니다. 1) 복잡한 쿼리 및 고급 SQL 기능, 2) 엄격한 데이터 무결성 및 산 준수, 3) 고급 공간 기능이 필요하며 4) 큰 데이터 세트를 처리 할 때 고성능이 필요합니다. PostgreSQL은 이러한 측면에서 잘 수행되며 복잡한 데이터 처리 및 높은 데이터 무결성이 필요한 프로젝트에 적합합니다.

MySQL 데이터베이스를 어떻게 보호 할 수 있습니까?MySQL 데이터베이스를 어떻게 보호 할 수 있습니까?Apr 24, 2025 am 12:04 AM

MySQL 데이터베이스의 보안은 다음 조치를 통해 달성 할 수 있습니다. 1. 사용자 권한 관리 : CreateUser 및 Grant 명령을 통한 액세스 권한을 엄격히 제어합니다. 2. 암호화 된 전송 : 데이터 전송 보안을 보장하기 위해 SSL/TLS를 구성합니다. 3. 데이터베이스 백업 및 복구 : MySQLDump 또는 MySQLPump를 사용하여 정기적으로 백업 데이터를 사용하십시오. 4. 고급 보안 정책 : 방화벽을 사용하여 액세스를 제한하고 감사 로깅 작업을 가능하게합니다. 5. 성능 최적화 및 모범 사례 : 인덱싱 및 쿼리 최적화 및 정기 유지 보수를 통한 안전 및 성능을 모두 고려하십시오.

MySQL 성능을 모니터링하는 데 사용할 수있는 몇 가지 도구는 무엇입니까?MySQL 성능을 모니터링하는 데 사용할 수있는 몇 가지 도구는 무엇입니까?Apr 23, 2025 am 12:21 AM

MySQL 성능을 효과적으로 모니터링하는 방법은 무엇입니까? Mysqladmin, Showglobalstatus, Perconamonitoring and Management (PMM) 및 MySQL Enterprisemonitor와 같은 도구를 사용하십시오. 1. MySQLADMIN을 사용하여 연결 수를보십시오. 2. showglobalstatus를 사용하여 쿼리 번호를보십시오. 3.pmm은 자세한 성능 데이터 및 그래픽 인터페이스를 제공합니다. 4. MySQLENTERPRISOMITOR는 풍부한 모니터링 기능 및 경보 메커니즘을 제공합니다.

MySQL은 SQL Server와 어떻게 다릅니 까?MySQL은 SQL Server와 어떻게 다릅니 까?Apr 23, 2025 am 12:20 AM

MySQL과 SqlServer의 차이점은 1) MySQL은 오픈 소스이며 웹 및 임베디드 시스템에 적합합니다. 2) SQLServer는 Microsoft의 상용 제품이며 엔터프라이즈 수준 애플리케이션에 적합합니다. 스토리지 엔진의 두 가지, 성능 최적화 및 응용 시나리오에는 상당한 차이가 있습니다. 선택할 때는 프로젝트 규모와 향후 확장 성을 고려해야합니다.

MySQL을 통해 어떤 시나리오에서 SQL Server를 선택할 수 있습니까?MySQL을 통해 어떤 시나리오에서 SQL Server를 선택할 수 있습니까?Apr 23, 2025 am 12:20 AM

고 가용성, 고급 보안 및 우수한 통합이 필요한 엔터프라이즈 수준의 응용 프로그램 시나리오에서는 MySQL 대신 SQLServer를 선택해야합니다. 1) SQLServer는 고 가용성 및 고급 보안과 같은 엔터프라이즈 수준의 기능을 제공합니다. 2) VisualStudio 및 Powerbi와 같은 Microsoft Ecosystems와 밀접하게 통합되어 있습니다. 3) SQLSERVER는 성능 최적화에서 우수한 성능을 발휘하며 메모리 최적화 된 테이블 및 열 스토리지 인덱스를 지원합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)