吐槽SQL Server触发器
本人用T-SQL,也用PL/SQL,发现T-SQL的触发器不好用,或者说我还不太会用,
比如说一个简单表定义如下:
create table emp
(
id int,
name varchar(20),
age int,
level int
);
先说Oracle的触发器很明确,很好用。
1、前触发还是后触发
操作之前触发用关键字Before,操作之后触发用After;
如更新之前,用Before Update
2、针对哪个表
用关键字on,
如对emp表操作时触发,用on emp
3、对哪些列操作时触发
用关键字of
如对name和age列操作时触发,用of name,age
4、对表的还是对行的,
对行的就是foreach row
5、对被操作的行,要拦截字段的新、旧值
字段新值就是:new.name,
字段旧值就是:old.name
对行的其它字段赋值直接,就可以new.level=5;
6、触发器的语句体
在begin与end之间的语句就是语句体
完整的一个Oracle触发器例子如下(作用是更新x、y字段时,把shape字段一并更新):
CREATE OR REPLACE TRIGGER tr_dz_xy_point
BEFORE UPDATE OF X,Y ON DZ
FOR EACH ROW
BEGIN
:new.Shape:=SDO_GEOMETRY (
2001, NULL,
SDO_POINT_TYPE (:new.X,:new.Y, NULL),
NULL,NULL
);
END;
对sql server(2000版)触发器的吐槽:
1、inserted、updated、deleted 代表什么?是表,是行?
是行为什么还要这样:
select @emp_lvl=i.level,@job_id = i.id from inserted i
既然inserted是出现在from后面,貌似是个表,
2、怎么区分触发器是对表的还是对行?
那如果inserted是个表,
想引用当前被插入的这个行怎么引用?
如果inserted.level是新值,deleted.level是旧值,(这是显而易见的)
那updated.level是新值还是旧值,如果是新值,要读取旧值怎么办?
3、前触发与后触发的混乱
有instead of、after、for 三类触发器,after从字面上易知是后触发,可是:
这个for是前触发还是后触发?
instead of又是前触发还是后触发?
4、触发器的语句体在哪?
就是As和GO之间吗,T-SQL是没有begin/end吗,用这么拙劣的语法结构。如果没写go呢?
5、要对被操作行的其它字段赋值怎么写?
[解决办法]
create table emp
(
id int,
name varchar(20),
age int,
level int
);
GO
--更多语法,请参考MSDN
CREATE TRIGGER tr_test ON tablename --针对哪个表
AFTER INSERT,UPDATE, DELETE --前触发还是后触发:INSTEAD OF,但会屏蔽SQL;操作之后触发用After(AFTER,for和after是一个意思)
as
begin --触发器的语句体(BEGIN END之间)
IF UPDATE(colmnA) --对哪些列操作时触发
BEGIN
SELECT * FROM DELETED
SELECT * FROM INSERTED --对表的还是对行的,需要自己写逻辑
UPDATE A
SET A.colnumB = 5--对被操作的行,要拦截字段的新、旧值
FROM tablename A
INNER JOIN DELETED D --存储所有旧值
ON a.id = D.id
INNER JOIN INSERTED i --存储所有新值
ON D.ID = I.ID
end
end
GO