触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。 触发器可以从 DBA_TRIGGERS ,USER_TRIGGERS 数据字典中查到(引用于百度百科------触发器(数据库原理术语)_百度百科)。
个人理解:即对数据库中主要表格数据变化的未雨绸缪(BEFORE)与亡羊补牢(AFTER)。例子中 oracle 以 PLSQL 为例,pgsql以 NAVICATE 为例。
-------------------------------------------oracle------------------------------------------------------------------------------
Create Or Replace Trigger 触发器名字 --([Tri_表名]作为触发器的名字 -> 单纯的容易看出来是对哪个表的触发器 )
After Delete Or Insert Or Update On 表名 --(表名 -> 主要表格,[After]关键字 -> 亡羊补牢)
For Each Row --(一般都是row行,其他的还没用到)
Declare
--用到的变量
v_id Number(24);
v_Type varchar2(10);
v_Cnt Number(10);
-- ......
Begin
If Inserting Then
v_Type := 'insert'; ---运行步骤,当异常后容易找错误程序位置
v_Prim := :New.Id; --- :New.Id -> 插入数据的id值
Insert Into 表名bak -- 表名bak:一般是其他库的表或者该库的备用表
(Id,
Name,
...
)
Values
(:New.Id,
:New.Name,
...
);
Commit; --做数据增改查,但不确定是否用提交事务,那么就写commit,错了再删!存过、函数亦如此。
If v_Prim = 123456 Then --存在特殊处理的数据,单独处理
For Cur In (Select Id From xxx ) Loop --这里的游标,只是用来演示,根据情况使用
Begin
If v_xx = 0 Then
...
End If;
Exception
When Others Then
Null;
End;
End Loop;
End If;
END; ---结束insert的触发,这里也可以不用end,那么下面的 update 钱的 if 可以改成 Elsif,用 end 方便可读性(菜鸟认为,if 对应 end 越近越容易读)。
if Updating Then
v_Type := 'update';
v_Prim := :Old.Id; ---更改的数据行的id值
Update 表名bak
Set Name = :New.Name
Where Id = v_Prim;
Commit;
Elsif Deleting Then
v_Type := 'delete';
v_Prim := :Old.Id;
Delete From 表名bak Where Id = v_Prim;
Commit;
Exception
When Others Then
v_Err_Msg := Substr(Sqlerrm, 1, 1000);
Insert Into Run_tri_Err ------对异常做个记录买房变查询
(Table_Name, Primval, Type, Errmsg, Errtime)
Values
(表名, v_Prim, v_Type, v_Err_Msg, Sysdate);
Commit;
End;
----------------------------------------------------pgsql-------------------------------------------------------------------
pgsql中需要定义一个触发器函数,然后在配置对应表调用的触发器函数(变成了两步,oracle一步)。
CREATE OR REPLACE FUNCTION "scheme名字"."触发器名字"() --scheme名字 触发器名字
RETURNS "pg_catalog"."trigger" AS $BODY$ ---这里是固定的
Declare
v_Prim numeric(24);
v_Err_Msg varchar(1000);
v_Type Char(1);
v_Cnt numeric(10);
v_cur cursor for -- 定义游标是在这里
Select Id From xxx;
BEGIN
IF (TG_OP = 'INSERT') then
v_Type := 'I';
v_Prim := New.Id; --这里的NEW前面没有 :
Insert Into 表名bak --同oracle
(Id,
Name,
...)
Values
(New.Id,
New.Name,
...
);
if New.Id = 12345 then
For Cur In v_cur Loop ---游标的使用
...
end loop;
end if;
RETURN NEW; ---返回处理完的数据,很关键,否则报错
END IF;
IF (TG_OP = 'UPDATE') then
v_Type := 'U';
v_Prim := Old.Id;
Update 表名bak
Set Name = New.Name,
...
Where Id = v_Prim;
RETURN NEW;
END IF;
IF (TG_OP = 'DELETE') then
v_Type := 'D';
v_Prim := Old.Id;
Delete From zhejiang_g5.Cm_Link Where Id = v_Prim;
RETURN NEW;
END IF;
Exception
When Others Then
v_Err_Msg := Substr('error', 1, 1000);
Insert Into Run_tri_Err
(Table_Name, Primval, Type, Errmsg, Errtime)
Values
('表名', v_Prim, v_Type, v_Err_Msg, current_date);
END;
$BODY$ ---这里是固定的
LANGUAGE plpgsql VOLATILE ---这里是固定的
COST 100 ---这里是固定的
查询表->设计表 -> 定义触发器(这样设置容易测试,同样也可以在触发器中直接添加)
剩下的就是测试通过了,触发器测试很费劲,愿君耐心!!不要像我一样抓狂~~哈哈哈哈