金蝶K3进度19触发器和调试操作流程Word下载.docx
《金蝶K3进度19触发器和调试操作流程Word下载.docx》由会员分享,可在线阅读,更多相关《金蝶K3进度19触发器和调试操作流程Word下载.docx(16页珍藏版)》请在冰豆网上搜索。
这时候,可以用InsteadOf触发器,把更新操作替换为向每个基本表进行更新。
3、触发器执行过程的中间表
触发器触发的时候有两个中间表:
插入表(instered表)和删除表(deleted表)。
这两张表的字段,和触发器应用主表的字段相同。
中间表存储的数据是执行插入、更新、删除操作的数据,当触发器执行完成后,这两张表就会被删除。
Inserted表的数据是待插入的数据,或是触发器修改后的数据。
deleted表的数据是插入前的原始数据。
如果是删除操作的触发器,deleted表是表示删除的数据。
4、For和After区别
for触发器不是before,sqlserver只有instead和after两种触发器。
for触发器,默认就是after触发器。
我之前还以为for触发器是数据插入、更新、删除操作执行前触发,after触发器是数据插入、更新、删除操作执行后触发,这是错误的认识。
5、同一个数据表两个、三个操作的触发器合并写法
afterinsert,update,delete触发器
(相当于是afterinsert触发器、afterupdate触发器、afterdelete触发器)
forinsert,update,delete触发器
(相当于是forinsert触发器、forupdate触发器、fordelete触发器)
insteadofinsert,update,delete触发器
(相当于是insteadofinsert触发器、insteadofupdate触发器、insteadofdelete触发器)
6、afterinsert触发器实例练习
本例没有对inserted临时数据进行更新,是通过关联fid直接更新数据表
createtable学生表5
(
fidintidentity(1,1),
fnamevarchar(100),
fsubjectvarchar(100),
fscorefloat
)
insertinto学生表5
(fname,fsubject,fscore)
select'
大明'
'
语文'
90
unionallselect'
数学'
80
英文'
85
小花'
王燕'
98
92
unionallselect'
--创建临时测试表,存储inserted数据表的临时数据
createtabletest6
--创建临时测试表,存储deleted数据表的临时数据
createtabletest7
--清空test6、test7
truncatetabletest6
truncatetabletest7
--创建afterinsert触发器
createtriggertrg_学生表5_insert
on学生表5
afterinsert
as
begin
--添加触发过程产生的inserted临时数据
insertintotest6(fname,fsubject,fscore)
selectfname,fsubject,fscorefrominserted
--添加触发过程产生的deleted临时数据
insertintotest7(fname,fsubject,fscore)
selectfname,fsubject,fscorefromdeleted
updatet1
setfscore=100
from学生表5t1
innerjoininsertedt2ont1.fid=t2.fid
end
--执行插入操作,触发afterinsert触发器
insertinto学生表5
王三'
60
--查询本次触发产生inserted临时数据
select*fromtest6
--查询本次触发产生deleted临时数据
select*fromtest7
结论:
afterinsert触发器不会产生deleted临时数据
--查询学生王三语文成绩是否由60分更新为100分
select*from学生表5
7、afterinsert触发器inserted修改前数据、修改后数据
本例对inserted临时进行更新,看最终是否更新到数据表
--清空test6、test7,对上一例的测试临时数据清理,以免干扰这次测试
--本例test6用来测试更新前的inserted临时数据
--本例test7用来测试更新后的inserted临时数据
--直接修改上例的afterinsert触发器
altertriggertrg_学生表5_insert
--添加修改前的inserted临时数据
--更新inserted临时数据
frominsertedt1
--添加修改后的inserted临时数据
insertintotest7(fname,fsubject,fscore)
触发器执行报错,逻辑表inserted表和deleted表不能被直接修改
8、afterupdate触发器实例练习
--创建afterupdate触发器
createtriggertrg_学生表5_update
afterupdate
--添加更新操作的原数据,即deleted临时数据
selectfname,fsubject,fscorefromdeleted
--添加更新操作后的已修改数据,即inserted临时数据
insertintotest6(fname,fsubject,fscore)
selectfname,fsubject,fscorefrominserted
setfscore=120
from学生表5t1
--执行更新操作
--在第一例中,我们通过新增触发器,把王三的语文成绩更新为100分。
--在本例中,我们做了更新操作,把王三的语文成绩更新为90分。
同时,
--我们还做了一个更新触发器,把王三的语文成绩更新为120分。
最终结果如何?
sett1.fscore=90
wherefname='
--查询本次测试的deleted临时数据
--这是更新操作前的旧数据
--查询本次测试的inserted临时数据
--这是更新操作后的修改数据
--查询数据表的实际结果
原数据王三的语文成绩是100分
更新操作后,王三的语文成绩是90分
更新操作激活触发器,王三的语文成绩是120分
最终结果是王三的语文成绩是120分
9、afterupdate字段级触发器
可以单列判断,也可以多列用or、and组合判断。
本例是单列判断。
本例更新的字段和触发器触发的字段不是同一个字段
--直接修改afterupdate触发器
altertriggertrg_学生表5_update
ifupdate(fsubject)
setfscore=150
--在上一例中,我们通过更新触发器,把王三的语文成绩更新为120分。
--我们还做了一个更新字段级的触发器,把王三的语文成绩更新为150分。
王三的语文成绩是更新操作设定的90分,而不是字段级更新触发器设定的150分
因为字段级更新字段触发被设为fsubject,本例更新的字段是fscore,所以,字段级
更新触发器并没有生效。
10、再测试字段级更新触发器
本例更新的字段和触发器触发的字段同一个字段
truncatetabletest7
ifupdate(fscore)
--在上一例中,我们通过更新触发器,把王三的语文成绩更新为90分。
--在本例中,我们做了更新操作,把王三的语文成绩更新为60分。
sett1.fscore=60
王三的语文成绩原来是90分。
更新操作执行后,王三的语文成绩是60分。
更新操作激活字段级更新触发器,刚好激活的字段是fscore,
触发器逻辑执行后,王三的语文成绩是150分
11、insteadofupdate触发器实例练习
--删除原添加afterupdate触发器,避免对insteadofupdate触发器造成干扰
droptriggertrg_学生表5_update
--创建insteadofupdate触发器
createtriggertrg_学生表5_std_update
insteadofupdate
selectfname,fsubject,fscorefrominserted
selectfname,fsubject,fscorefromdeleted
setfscore=300
--在上例中,王三的语文成绩为150分。
--在本例中,我们做了更新操作,把王三的语文成绩更新为200分。
--我们还做了一个替代更新触发器,把王三的语文成绩更新为300分。
sett1.fscore=200
虽然是替代触发器,但是在逻辑表inserted临时数据有体现更新操作后的修改数据。
只是在替代触发器中,更新操作并没有被生效,而是改为执行替代触发器的T-SQL逻辑语句。
原数据王三的语文成绩是150分
更新操作后,王三的语文成绩应该是200分,实际上并没有执行这步,该步替代为执
行触发器逻辑。
更新操作激活触发器,王三的语文成绩是300分
最终结果是王三的语文成绩是300分
12、触发器调试
触发器执行过程的临时数据,在实际操作时,是没法被测试到的。
调试过程如下:
1、通过增建测试表,并根据需要放上和被测试临时数据相同数据类型的字段
2、然后在触发器代码过程中,把这个临时数据插入到测试表。
3、执行插入、更新、删除操作以后,触发器就被激活触发执行后。
4、这时候再到测试表去查询测试表的数据,以此迂回去跟踪到触发过程,并分析触发逻辑是否正确。
以上面8、afterupdate触发器案例练习为例,在这个例子中,我们为了跟踪inserted和deleted这两个逻辑表执行过程中产生的临时数据。
但是,临时数据在执行结束以后,是查不到的。
所以,我们需要在过程进行跟踪,最笨的办法,就是在触发器执行过程,把临时数据保存到实际的数据表里面,这样,执行结束后,临时数据还能查的到。
实际调试过程如下:
1、为了隔离数据,我们建了test6、test7两个数据表,分别对应inserted和deleted表。
因为inserted和deleted表临时存储的是学生表5的触发数据,所以他们有三个字段fname、
fsubject、fscore。
这里,我们为了好辨识和一一对应,也取名一模一样。
这里,也可以
用简易字段来建立,比如命名为t1(字符型)、t2(字符型)、t3(浮点型)。
我这里是为了测试inserted和deleted表,实际测试时,可能是为了测试业务逻辑产生
的临时数据。
要懂得灵活运用,举一反三。
2、在触发器代码中,我们加入了两个插入语句,用来保存需要被测试的临时数据
3、执行完更新操作后
4、再到数据库查询临时结果集。
有时候,我们不只是测试一次,可能会多次测试。
所以,在下一次测试前,你要把测试表的数据清空,或者给测试表加上主键自增FID字段,然后记住上一次测试的FID数值是多少,这样也可以区分多次测试产生的临时数据。
13、避免触发器全表更新
很多金蝶的实施顾问,可能SQL编写能力较薄弱,经常写的更新触发器都是直接全表更新,而且经常是针对出入库单据表进行全表更新。
由于出入库单据表包含了采购入库、委外入库、产品入库、其他入库、调拨单、销售出库、委外出库、生产领料、其他出库等这些出入库单据,全表更新影响较大,而且更新的数据量非常巨大。
这样一个是对数据产生的风险影响较大,第二个是影响性能。
在触发器逻辑中,我们尽量只是针对这条被触发的数据进行处理,使用innerjoin这种内连接,关联inserted的关联字段,比如单据头内码、物料id、单据体分录内码等。
我们的测试例子中,也是针对被触发的这条数据进行更新,用的是关联的fid。
除非业务处理逻辑需要,否则尽量避免触发器中进行全表更新。