首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

吐槽SQL Server触发器解决方法

2013-09-07 
吐槽SQL Server触发器本人用T-SQL,也用PL/SQL,发现T-SQL的触发器不好用,或者说我还不太会用,比如说一个简

吐槽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


[解决办法]
对sql server(2000版)触发器的吐槽:

1、inserted、updated、deleted 代表什么?是表,是行? 回复:没有updated表,另外两个是:
触发器中
select?*?from?inserted??--取得新增或修改后的内容,结构与原表一样

select?*?from?deleted??--取得删除或修改前的内容,结构与原表一样


2、怎么区分触发器是对表的还是对行?
回复:那两个是表,但是跟源表结构一样,所以如果源表有主键,也可以在这两个表里面定位到你要的行集


3、前触发与后触发的混乱
回复:这个问题直接去看联机丛书,有介绍,也有例子
 
4、触发器的语句体在哪?

  回复:同上

5、要对被操作行的其它字段赋值怎么写?
回复:其他字段?你可以定义变量然后再操作
[解决办法]
学过触发器的概念,但在实际工作中很少用到,就从直观的角度,确实oracle的触发器提供了比SQL Server更明确的实现方式,比如前触发还是后出发。

但这些其实都是表面的东西,我觉得你还是需要更加全面的学习SQL Server触发器,比如insead of一般用于给视图建立触发器,另外,go只表示前面是一个批处理,如果后面没其他语句,那这个go写不写没什么区别的。

总体说来,SQL Server和Oracle的很多语法和写法习惯,还是有很多不一样的地方,你需要逐步区分了解,不过你运用Oracle得到的经验,我觉得在SQL Server上也会对你很有帮助的。
[解决办法]
对一个逻辑,不用触发器,也必须写个SP(或者在前端写N多个指令,也还是一个事务)
那么为什么不使用触发器去完成??
条条道路通罗马,各有选择也不奇怪

SQL SERVER触发器足够好用,同样,用贯SQL SERVER再玩ORACLE,也非常别扭
MYSQL就玩具了点

热点排行