跨数据库触发器的作用的触发器相关

数据库触发器详解
Mysql的触发器和存储过程一样,都是嵌入到的一段程序。触发器是mysql5新增的功能,目前线上凤巢、北斗系统以及哥伦布系统使用的均是mysql5.0.45版本,很多程序比如fc-star管理端,sfrd(das),dorado都会用到触发器程序,实现对于数据库增、删、改引起事件的关联操作。本文介绍了触发器的类型和基本使用方法,讲述了触发器使用中容易产生的误区,从mysql中得到触发器执行顺序的结论,本文最后是实战遭遇的触发器经典案例。没有特殊说明时,本文的实验均基于mysql5.0.45版本。
2&& Mysql触发器的类型
2.1&& Mysql触发器的基本使用
创建触发器。创建触发器语法如下:
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
其中trigger_name标识触发器名称,用户自行指定;
trigger_time标识触发时机,用before和after替换;
trigger_event标识触发事件,用insert,update和delete替换;
tbl_name标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt是触发器程序体;触发器程序可以使用begin和end作为开始和结束,中间包含多条语句;
下面给出sfrd一个触发器实例:
CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER trig_useracct_update
AFTER UPDATE
ON SF_User.useracct FOR EACH ROW
IF OLD.ulevelid = 10101 OR OLD.ulevelid = 10104 THEN
IF NEW.ulevelid = 10101 OR NEW.ulevelid = 10104 THEN
if NEW.ustatid != OLD.ustatid OR NEW.exbudget != OLD.exbudget THEN
INSERT into FC_Output.fcevent set type = 2, tabid = 1, level = 1, userid = NEW.userid, ustatid = NEW.ustatid, exbudget = NEW.
INSERT into FC_Output.fcevent set type = 1, tabid = 1, level = 1, userid = NEW.userid, ustatid = NEW.ustatid, exbudget = NEW.
上述触发器实例使用了OLD关键字和NEW关键字。OLD和NEW可以引用触发器所在表的某一列,在上述实例中,OLD.ulevelid表示表SF_User.useracct修改之前ulevelid列的值,NEW.ulevelid表示表SF_User.useracct修改之后ulevelid列的值。另外,如果是insert型触发器,NEW.ulevelid也表示表SF_User.useracct新增行的ulevelid列值;如果是delete型触发器OLD.ulevelid也表示表SF_User.useracct删除行的ulevelid列原值。
另外,OLD列是只读的,NEW列则可以在触发器程序中再次赋值。
上述实例也使用了IF,THEN ,ELSE,END IF等关键字。在触发器程序体中,在beigin和end之间,可以使用顺序,判断,循环等语句,实现一般程序需要的逻辑功能。
查看触发器。查看触发器语法如下,如果知道触发器所在数据库,以及触发器名称等具体信息:
SHOW TRIGGERS from SF_User like &usermaps%&;&&&&&& //查看SF_User库上名称和usermaps%匹配的触发器
如果不了解触发器的具体的信息,或者需要查看数据库上所有触发器,如下:
SHOW TRIGGERS;&&&&&& //查看所有触发器
用上述方式查看触发器可以看到数据库的所有触发器,不过如果一个库上的触发器太多,由于会刷屏,可能没有办法查看所有触发器程序。这时,可以采用如下方式:
Mysql中有一个information_schema.TRIGGERS表,存储所有库中的所有触发器,desc information_schema. TRIGGERS,可以看到表结构:
+----------------------------+--------------+------+-----+---------+-------+
| Field&&&&&&&&&&&&&&&&&&&&& | Type&&&&&&&& | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------+-------+
| TRIGGER_CATALOG&&&&&&&&&&& | varchar(512) | YES |&&&& | NULL&&& |&&&&&& |
| TRIGGER_SCHEMA&&&&&&&&&&&& | varchar(64) | NO&& |&&&& |&&&&&&&& |&&&&&& |
| TRIGGER_NAME&&&&&&&&&&&&&& | varchar(64) | NO&& |&&&& |&&&&&&&& |&&&&&& |
| EVENT_MANIPULATION&&&&&&&& | varchar(6) &&| NO&& |&&&& |&&&&&&&& |&&&&&& |
| EVENT_OBJECT_CATALOG&&&&&& | varchar(512) | YES |&&&& | NULL&&& |&&&&&& |
| EVENT_OBJECT_SCHEMA&&&&&&& | varchar(64) | NO&& |&&&& |&&&&&&&& |&&&&&& |
| EVENT_OBJECT_TABLE&&&&&&&& | varchar(64) | NO&& |&&&& |&&&&&&&& |&&&&&& |
| ACTION_ORDER&&&&&&&&&&&&&& | bigint(4)&&& | NO&& |&&&& | 0&&&&&& |&&&&&& |
| ACTION_CONDITION&&&&&&&&&& | longtext&&&& | YES |&&&& | NULL&&& |&&&&&& |
| ACTION_STATEMENT&&&&& &&&&&| longtext&&&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
| ACTION_ORIENTATION&&&&&&&& | varchar(9)&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
| ACTION_TIMING&&&&&&&&&&&&& | varchar(6)&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
| ACTION_REFERENCE_OLD_TABLE | varchar(64) | YES |&&&& | NULL&&& |&&&&&& |
| ACTION_REFERENCE_NEW_TABLE | varchar(64) | YES |&&&& | NULL&&& |&&&&&& |
| ACTION_REFERENCE_OLD_ROW&& | varchar(3)&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
| ACTION_REFERENCE_NEW_ROW&& | varchar(3)&& | NO&& |&&&& |&&&&&&&& |&&& &&&|
| CREATED&&&&&&&&&&&&&&&&&&& | datetime&&&& | YES |&&&& | NULL&&& |&&&&&& |
| SQL_MODE&&&&&&&&&&&&&&&&&& | longtext&&&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
| DEFINER&&&&&&&&&&&&&&&&&&& | longtext&&&& | NO&& |&&&& |&&&&&&&& |&&&&&& |
+----------------------------+--------------+------+-----+---------+-------+
这样,用户就可以按照自己的需要,查看触发器,比如使用如下语句查看上述触发器:
select * from information_schema. TRIGGERS where TRIGGER_NAME= 'trig_useracct_update'\G;
删除触发器。删除触发器语法如下:
DROP TRIGGER [schema_name.]trigger_name
2.2&& Msyql触发器的trigger_time和trigger_event
现在,重新注意到trigger_time和trigger_event,上文说过,trigger_time可以用before和after替换,表示触发器程序的执行在sql执行的前还是后;trigger_event可以用insert,update,delete替换,表示触发器程序在什么类型的sql下会被触发。
在一个表上最多建立6个触发器,即1)before insert型,2)before update型,3)before delete型,4)after insert型,5)after update型,6)after delete型。
触发器的一个限制是不能同时在一个表上建立2个相同类型的触发器。这个限制的一个来源是触发器程序体的&begin和end之间允许运行多个语句&(摘自mysql使用手册)。
另外还有一点需要注意,msyql除了对insert,update,delete基本操作进行定义外,还定义了load data和replace语句,而load data和replace语句也能引起上述6中类型的触发器的触发。
Load data语句用于将一个文件装入到一个数据表中,相当与一系列insert操作。replace语句一般来说和insert语句很像,只是在表中有primary key和unique索引时,如果插入的数据和原来primary key和unique索引一致时,会先删除原来的数据,然后增加一条新数据;也就是说,一条replace sql有时候等价于一条insert sql,有时候等价于一条delete sql加上一条insert sql。即是:
?&& Insert型触发器:可能通过insert语句,load data语句,replace语句触发;
?&& Update型触发器:可能通过update语句触发;
?&& Delete型触发器:可能通过delete语句,replace语句触发;
3&& Mysql触发器的执行顺序
先抛出触发器相关的几个问题
3.1&& 如果before类型的触发器程序执行失败,sql会执行成功吗?
实验如下:
1)在FC_Word.planinfo中建立before触发器:
DELIMITER |
create trigger trigger_before_planinfo_update
before update
ON FC_Word.planinfo FOR EACH ROW
insert into FC_Output.abc (planid) values (New.planid);
2)查看:mysql& select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
|&&&&&&& 2 |
+----------+
3)执行sql:
update planinfo set showprob=200 where planid=1;&&&&& 触发触发器程序;
4)由于不存在FC_Output.abc,before触发器执行失败,提示:
ERROR ): Table 'FC_Output.abc' doesn't exist
5)再次查看:
mysql& select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
|&&&&&&& 2 |
+----------+
即修改sql未执行成功。即如果before触发器执行失败,sql也会执行失败。
3.2&& 如果sql执行失败,会执行after类型的触发器程序吗?
实验如下:
1)在FC_Word.planinfo中建立after触发器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
INSERT INTO FC_Output.fcevent set level = 2, type = 2, tabid = 5, userid = NEW.userid, planid = NEW.planid, planstat2 = NEW.planstat2, showprob = NEW.showprob, showrate = NEW.showrate, showfactor = NEW.showfactor, planmode = NEW.
2)查看触发表:
mysql& select * from FC_Output.fcevent where planid=1;
Empty set (0.00 sec)
没有planid=1的记录
3)执行sql:
mysql& update planinfo set showprob1=200 where planid=1;
4)由于不存在showprob1列,提示错误:
ERROR ): Unknown column 'showprob1' in 'field list'
5)再次查看触发表:
mysql& select * from FC_Output.fcevent where planid=1;
Empty set (0.00 sec)
触发表中没有planid=1的记录,sql在执行失败时,after型触发器不会执行。
3.3&& 如果after类型的触发器程序执行失败,sql会回滚吗?
实验如下:
1)在FC_Word.planinfo中建立after触发器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
insert into FC_Output.abc (planid) values (New.planid);
2)查看:mysql& select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
|&&&&&&& 2 |
+----------+
3)执行sql:
update planinfo set showprob=200 where planid=1;触发触发器程序;
4)由于不存在FC_Output.abc,after触发器执行失败,提示:
ERROR ): Table 'FC_Output.abc' doesn't exist
5)再次查看:
mysql& select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
|&&&&&&& 2 |
+----------+
即修改sql未执行成功。即如果after触发器执行失败,sql会回滚。
这里需要说明一下,上述实验所使用的mysql引擎是innodb,innodb引擎也是目前线上凤巢系统、北斗系统以及哥伦布系统所使用的引擎,在innodb上所建立的表是事务性表,也就是事务安全的。&对于事务性表,如果触发程序失败(以及由此导致的整个语句的失败),该语句所执行的所有更改将回滚。对于非事务性表,不能执行这类回滚&(摘自mysql使用手册)。因而,即使语句失败,失败之前所作的任何更改依然有效,也就是说,对于innodb引擎上的数据表,如果触发器中的sql或引发触发器的sql执行失效,则事务回滚,所有操作会失效。
3.4&& mysql触发器程序执行的顺序
当一个表既有before类型的触发器,又有after类型的触发器时;当一条sql语句涉及多个表的update时,sql、触发器的执行顺序经过mysql源码包装过,有时比较复杂。
可以先看一段mysql的源代码,当SQL中update多表的时候,Mysql的执行过程如下(省去了无关代码):
/* 遍历要更新的所有表*/
for (cur_table= update_ cur_ cur_table= cur_table-&next_local)
org_updated = updated
/* 如果有BEFORE 触发器,则执行;如果执行失败,跳到err2位置*/
if (table-&triggers &&
table-&triggers-&process_triggers(thd, TRG_EVENT_UPDATE,TRG_ACTION_BEFORE, TRUE))
goto err2;
/*执行更新,如果更新失败,跳到err位置*/
if(local_error=table-&file-&update_row(table-&record[1], table-&record[0])))
updated++; // 更新计数器
/* 如果有AFTER 触发器,则执行;如果执行失败,跳到err2位置*/
if (table-&triggers &&
table-&triggers-&process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))
goto err2;
/*标志错误信息,写日志等*/
/*恢复执行过的操作*/
check_opt_it.rewind();
/*如果执行了更新,且表是有事务的,做标志*/
if (updated != org_updated)
if (table-&file-&has_transactions())
transactional_tables= 1;
从上面代码可以找到本章开始时抛出问题的答案。
1)&& 如果before型触发器执行失败,直接goto跳到err2位置,不会执行后续sql语句;
2)&& 如果sql执行失败,直接goto跳到err位置,不会执行或许的after型触发器;
3)&& 如过after触发器执行失败,goto到err2位置,恢复执行过的操作,且在事务型的表上做标记。
另外,在使用复杂的sql时,由于有些复杂的sql是mysql自己定义的,所以存在不确定性,使用简单的sql比较可控。
4&& Mysql触发器在数据库同步中的表现
4.1&& 触发器运行失败时,数据库同步会失败吗?
有同步关系如下dbA?dbB。初始时同步正常。
1)在dbB上建立触发器:
DELIMITER |
create trigger trigger_after_planinfo_update
after update
ON FC_Word.planinfo FOR EACH ROW
insert into FC_Output.abc (planid) values (New.planid);
2)在dbA上执行sql,执行成功;
mysql& update planinfo set showprob=200 where planid= 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
3)由于dbB上没有FC_Output.abc表,触发器会执行失败,这时,检查一下同步状态:
Slave_IO_Running: Yes
Slave_SQL_Running: NO
Last_Errno: 1146
Last_Error: Error 'Table 'FC_Output.abc' doesn't exist' on query. Default database: 'FC_Word'. Query: 'update planinfo set showprob=200 where planid= 1'
可以看到IO线程运行正常,sql线程运行失败,并提示触发器运行失败的错误信息。
回忆一下3.1和3.3所述部分,无论是before部分的触发器还是after类型的触发器,对于innodb引擎,当触发器执行失败时,相应sql也会执行失败,所以数据库同步也会失败。
4.2&& 创建、删除触发器写bin-log
创建和删除触发器的语句也会写入bin-log里,所以也会如一般的insert,update,delete语句一样同步到下游数据库中,即上游创建触发器,下游也会创建。
这里再引出两个小问题:有同步关系dbA?dbB,
1)&& 在dbA上创建一个触发器,如果dbB上已经有同表同类型的触发器,同步状态如何?
2)&& 在dbB上删除一个触发器,如果dbB上没有对应触发器,同步状态如何?
这两个问题可以类比同步中的insert语句和delete语句,答案就是
1)&& 同步失败,因为不允许重复创建同表同类型的触发器;
2)&& 同步正常,因为drop一个不存在的触发器,不影响运行结果;
5&& Mysql触发器经典案例
5.1&& 案例1 一条sql涉及多个表的update时,触发得到update之前的旧值
【现象】表test_info上建有触发器如下:
CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER trig_test_info_update
AFTER UPDATE
ON FC_Word.test_info FOR EACH ROW
DECLARE tlevel INTEGER DEFAULT 0;
DECLARE ttype INTEGER DEFAULT 0;
SET tlevel = 4;
SET ttype = 33;
INSERT INTO TEST_Output.fcevent (te, le, uid, pid, uid, wid, bi, mbid, wl) SELECT ttype, tlevel, NEW.uid, NEW.pid, NEW.uid, NEW.wid, NEW.bi, NEW.mbid, wl FROM TEST_Word.wext2 where wid = NEW.
/*。。。其余部分逻辑省略*/
这个触发器程序有点长,可以单看飘黄的两句,即更新操作满足第一个条件执行飘黄语句时,触发器的行为。触发器是建立在test_info表上的,飘黄语句中可以看到,也需要查询wext2表。
执行如下sql1:
Update test_info a, wext2 b set a.th=(a.th+1), a.w4=(a.w4&8), b.wl=NULL where a.wid=b.wid and a.wid=;
可以看到sql中既修改了test_info2表,同时修改了wext2表,程序原意是触发得到wext2表wl字段修改后的新值(即NULL);不过实验得到,执行上述sql后,触发器程序查询到的wurl是sql修改之前的旧值。
再执行下面类似sql2:
Update wext2 a, test_info2 b set b.th=(b.th+1), b.w4=(b.w4&8), a.wl=NULL where a.wid=b.wid and a.wid=;
实验的到,执行上述sql后,触发器程序查询到的wurl是sql修改之后的新值。
【原因】原因当然与sql中的别名a,b无关,而是和wext2表和test_info表的书写顺序有关。如本文3.4部分所述,一条sql涉及多个表的update操作时,数据表字段、触发器执行顺序是mysql源码包装过的。在执行上述sql1时,先执行test_info的更新,然后是after触发器,最后是wext2的更新,也就是说,在执行after触发器时,wext2还没有进行更新,所以触发得到的是旧值。而执行sql2时,先执行wext2更新,然后是test_info更新,最后是after触发器,也就是说,在执行after触发器时,wext2已经更新完毕,所以出去得到的是新值。
引起上述现象是顺序关系的,无论该表是否支持事务。在使用复杂的sql时,由于有些复杂的sql是mysql自己定义的,所以存在不确定性,存在风险,使用简单的sql比较可控。
5.2&& 案例2 mysql5.0.19版本修改表结构后触发器失效
【现象】userpref表上建有after类型触发器,修改userpref表的外键关联后,在userpref表中的新增记录没有触发下来,即触发器失效。
【原因】mysql5.0.19修改表结构是,触发器消失。这是mysql5.0.19的一个bug,在创建触发器时,会把触发器的内容保存在information_schema.TRIGGERS表中,同时在var目录下创建触发器的数据库目录下创建一个触发器名称为前缀,以TRN为后缀的文件,当修改触发器的表时,information_schema.TRIGGERS表的内容会删除,导致触发器消失。
在mysql5.0.45版本中,这个bug已经被修复。Mysql5.0.45版本的触发器,无论是修改表的索引、外键,还是改变表字段,触发器都不会失效。
5.3&& 案例3 删除数据表后触发器失效
【现象】联调环境中存在dbA?dbB,主库dbA上没有触发器,在从库dbB上的FC_Word.wnegative表,FC_Word.wbuget 表上建有触发器;触发器开始运行正常,期间没有对从库的任何直接操作,有一日发现对wnegative表上的修改无法触发。查看从库状态,同步正常;用select TRIGGER_NAME from information_schema.TRIGGERS发现wnegative表上的触发器消失了;在var/FC_Word目录下也没有wnegative的.TRN文件,wnegative表上的触发器不见了。
【分析】查找dbB的查询日志,发现有一条:
:27:45 135939 Query&&&&&& DROP TABLE IF EXISTS `wnegative`
135939 Query&&&&&& CREATE TABLE `wnegative` (
KEY `Index_wnegative_planid` (`planid`),
KEY `Index_wnegative_unitid` (`unitid`)
135939 Query&&&&&& /*!40000 ALTER TABLE `wnegative` DISABLE KEYS */
:27:46 135939 Query&&&&&& INSERT INTO `wnegative` VALUES (614,1,);
可以看到,在:27:45时,删除了表wnegative,紧接着有创建表wnegative;查找触发表发现,在:27:45时间后对wnegative的修改就没有触发了,而在这个之前对wnegative的修改是触发正常的。故,怀疑对wnegative表的删除使wnegative表上的触发器也被删除。对wnegative表的删除是在主库dbA上操作后,被同步到dbB上。
【原因】在删除wnegative表时,mysql同时删除了wegative表上的触发器。
可以通过下面实验证明上述猜测:
1)&& 首先在wnegative建立after insert型触发器;
2)&& 增加一条wnegative中记录;
3)&& 查看结果发现触发器正确触发;
4)&& 删除wnegative表;
5)&& 使用select TRIGGER_NAME from information_schema.TRIGGERS查看所有触发器,wnegative表上触发器已经不存在了;同时到var/FC_Word目录下,对应触发器的.TRN文件也不存在了;
6)&& 重新创建wnegative表,并增加一条wnegative中记录;没有了wnegative表上触发器,自然也不能触发任何结果。
6&& 结束语
Mysql中的触发器功能已经在凤巢系统的各个模块中有广泛应用,究其细节,还有很多值得注意的地方;本文建立在实验和案例的基础上,数据库基于线上系统使用的mysql5.0.45版本,分析了触发器相关的一些特殊情况下msyql的处理方式。
摘自 磊.Y的博客Sql&Server&触发器实现多表之间同步增加、删除与更新
Sql Server&实现多表之间同步增加、删除与更新
定义: 何为触发器?在SQL
Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。(SQL Server
2000定义了新的触发器,这里不提)
我为什么要使用触发器?比如,这么两个表:
Create Table
Student(&&&&&&&&&&&&
StudentID int primary
Create Table
BorrowRecord(&&&&&&&&&&&&&
--学生借书记录表
BorrowRecord& int
identity(1,1),&&&&&
--流水号&&
StudentID&&&&
,&&&&&&&&&&&&&&&&&&
BorrowDate&&&
datetime,&&&&&&&&&&&&&&
--借出时间
ReturnDAte&&&
Datetime,&&&&&&&&&&&&&&
--归还时间
分别创建增加、删除、更新的触发器(Trigger)来达到两张表之间数据同步的目的。
1:数据同步增加:
如有两张表——A表和B表,创建触发器使当A表插入数据后B表也同步插入数据。其中B表插入数据的字段需要同A表中的字段相对应。
CREATE TRIGGER 触发器名称&
AFTER INSERT&
AS BEGIN INSERT INTO&
B表(B表字段1,B表字段2,B表字段3)
SELECT A表字段1,A表字段2,A表字段3&
FROM INSERTED
2.数据同步删除:
如有两张表——A表和B表,创建触发器使当A表删除数据后B表也同步删除数据。其中B表与A表应有相应主键关联。
CREATE TRIGGER 触发器名称&
AFTER DELETE&
AS BEGIN DELETE B表&
B表主键 IN(&
SELECT A表主键
FROM DELETED)&
3.数据同步更新:
如有两张表——A表和B表,创建触发器使当A表数据更新后B表也同步更新数据。
CREATE TRIGGER 触发器名称
AFTER UPDATE&
update B表
B.B表字段1=A.A表字段1&&
B表 AS B,INSERTED AS
WHERE B.B表主键=A.A表主键
我为什么要使用触发器?比如,这么两个表:
Create Table
Student(&&&&&&&&&&&&
StudentID int primary
Create Table
BorrowRecord(&&&&&&&&&&&&&
--学生借书记录表
BorrowRecord& int
identity(1,1),&&&&&
--流水号&&
StudentID&&&&
,&&&&&&&&&&&&&&&&&&
BorrowDate&&&
datetime,&&&&&&&&&&&&&&
--借出时间
ReturnDAte&&&
Datetime,&&&&&&&&&&&&&&
--归还时间
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
&&& 等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
&&& Create
Trigger truStudent
Student&&&&&&&&&&&&&&&&&&&&&&&
--在Student表中创建触发器
Update&&&&&&&&&&&&&&&&&&&&&&&&
--为什么事件触发
As&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
--事件触发后所要做的事情
Update(StudentID)&&&&&&&&&&&
Update BorrowRecord&
Set StudentID=i.StudentID
From BorrowRecord br , Deleted& d ,Inserted
--Deleted和Inserted临时表
Where br.StudentID=d.StudentID
end&&&&&&&
&&&&&&&&&&&&&&&&
理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted
与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
&&& 一个系统中有两个虚拟表用于存储在表中记录改动的信息,分别是:
&&&&&&&&&&&&&&&&&&&&&&&&&&&
虚拟表Inserted&&&&&&&&&&&&&&&&&&&
虚拟表Deleted
在表记录新增时&&&
存放新增的记录&&&&&&&&&&&&&&&&&&&&&&&
不存储记录
修改时&&&&&&&&&
存放用来更新的新记录&&&&&&&&&&&&&&&&&
存放更新前的记录
删除时&&&&&&&&&
不存储记录&&&&&&&&&&&&&&&&&&&&&&&&&&&
存放被删除的记录
&&& 一个Update
的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
&&& Create
trigger trdStudent
On Student
for Delete
Delete BorrowRecord&
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
这里我们只讲解最简单的触发器。复杂的容后说明。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。此心光明浩然气,亦复何求”已“”功“”名“。
帖子186&精华0&金币993 枚&声望4 点&
两个都是MSSQL数据库吗
帖子186&精华0&金币993 枚&声望4 点&
服务器已经给了提示了
服务器 'CLGLTEST' 上的 MSDTC 不可用。
帖子623&精华0&金币338 枚&声望0 点&
对,先看服务启动没,启动后再看报什么
帖子358&精华0&金币942 枚&声望0 点&
慎用触发器
[通过 QQ、MSN 分享给朋友]}

我要回帖

更多关于 数据库触发器的作用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信