触发器-存储过程-数据库安全.doc
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《触发器-存储过程-数据库安全.doc》由会员分享,可在线阅读,更多相关《触发器-存储过程-数据库安全.doc(15页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、基于SQL SERVER触发器技术的实现时间:2006-6-12 上午 07:51:28来源:DZY学习资料库阅读946次 在数据库管理系统中,如何保证数据库中的数据完整性是一项重要的课题。数据完整性是指存储在数据库的数据的一致性。主要体现在以下几个方面:实体完整性(EntityIntegrity)、域完整性(DomainIntegrity)、参照完整性(ReferentialIntegrity)和用户的自定义完整性(UserdefineIntegrity)。目前,已有多种方法来解决这个问题。从最基本的数据类型,到多种形式的约束条件,虽然都提出了数据完整性的解决方案,但由于这些方法较为简单,不
2、能解决比较复杂的数据完整性问题。而触发器(Trigger)作为一种高级的技术,可以轻松地解决任何有关保证数据完整性的问题。一、在SQLSERVER环境中使用触发器1触发器的工作原理触发器是一种特殊类型的存储过程,它与表紧密联系在一起,在对表进行插入、删除和更新时,如该表(也称触发器表)有相应操作类型的触发器,则触发器便会自动触发执行。触发器分为INSERT触发器、DELETE触发器和UPDATE触发器3类。当向触发器表中插入数据时,INSERT触发器将触发执行,新的记录会增加到触发器表和inseted表中;当删除触发器表中的数据时,DELETE触发器将触发执行,被删除的记录会存放到delete
3、d表中;当更新触发器表中的数据时,相当于插入一条新记录和删除一条旧记录,此时UPDATE触发器将触发执行,表中原有的记录存放到deleted表中,修改后的记录插入到inserted表中。其中inserted表和deleted表是两个逻辑表,由系统来维护,不允许用户直接对这两个表进行修改。它们存放于内存中,不存放在数据库中。这两个表的结构总是与被该触发器作用的表的结构相同。触发器工作完成后,与该触发器相关的这两个表也会被删除。deleted表用于存储SQL语言中DELETE和UPDATE语句所影响的行的复本。在执行DELETE或UPDATE语句时,行从触发器表中删除,并传输到deleted表中。
4、deleted表和触发器表通常没有相同的行;inserted表用于存储SQL语言中INSERT和UPDATE语句所影响的行的副本。在一个插入或更新事务处理中,新建行被同时添加到inserted表和触发器表中。inserted表中的行是触发器表中新行的副本。2触发器的实现步骤在笔者开发的教材管理系统中,建立了一个教材数据库JCSJK,其中有教材表JCB和教材进出明细表MXB,需要在对MXB进行插入、删除和修改时,动态地修改JCB中对应教材的库存数量。下面举例说明触发器的实现步骤。为减少篇幅,对表结构作了简化处理。以下操作在MicrosoftSQLSERVER环境中完成。(1)建立教材表JCB,并
5、定义主键CREATETABLEdbo.JCB(教材代码char(10)NOTNULL,教材名char(30)NOTNULL,价格decimal(18,2)NOTNULL,库存量intNULL,出版社char(20)NULL)ONPRIMARYALTERTABLEdbo.JCBWITHNOCHECKADDCONSTRAINTPKJCBPRIMARYKEYCLUSTERED(教材代码)ONPRIMARY(2)建立教材进出明细表MXB,并定义主键和外?brCREATETABLEdbo.MXB(教材代码char(10)NOTNULL,日期datetimeNOTNULL,教材进intNULL,教材出in
6、tNULL,备注char(40)NULL)ONPRIMARYALTERTABLEdbo.MXBWITHNOCHECKADDCONSTRAINTPKMXBPRIMARYKEYCLUSTERED(教材代码,日期)ONPRIMARYALTERTABLEdbo.MXBADDCONSTRAINTFKMXBJCBFOREIGNKEY(教材代码)REFERENCESdbo.JCB(教材代码)ONDELETECASCADEONUPDATECASCADE图1显示了JCB和MXB两个表的关系。(3)在MXB上建立INSERT触发器CREATETRIGGERMXBINSEONdbo.MXBFORINSERTASUP
7、DATEJCBSET库存量=库存量+(SELECT教材进-教材出FROMINSERTED)FROMJCB,INSERTEDWHEREJCB.教材代码=INSERTED.教材代码(4)在MXB上建立DELETE触发器CREATETRIGGERMXBDELEONdbo.MXBFORDELETEASUPDATEJCBSET库存量=库存量-(SELECT教材进-教材出FROMDELETED)FROMJCB,DELETEDWHEREJCB.教材代码=DELETED.教材代码HT(5)在MXB上建立UPDATE触发器CREATETRIGGERMXBUPDAONdbo.MXBFORUPDATEASBEGIN
8、UPDATEJCBSET库存量=库存量-(SELECT教材进-教材出FROMDELETED)FROMJCB,DELETEDWHEREJCB.教材代码=DELETED.教材代码UPDATEJCBSET库存量=库存量+(SELECT教材进-教材出FROMINSERTED)FROMJCB,INSERTEDWHEREJCB.教材代码=INSERTED.教材代码END通过以上步骤,设置了MXB表的3类触发器,当用户对MXB表进行插入、删除和修改时,将根据MXB中教材进出的情况动态地修改JCB中对应教材的库存量。由于在触发器中,涉及到的inserted表和deleted表均存放在内存中,因此,触发器的执行
9、速度较快。3设计触发器的考虑在写触发器代码时需要考虑的一个重要问题就是,引发触发器的语句可以是一个影响单行的语句,也可以是一个影响多行的语句。这在UPDATE和DELETE触发器中很常见,因为这些语句经常作用于多行。而这在INSERT触发器中就比较少见,因为基本的INSERT语句只添加一行。然而,由于INSERT触发器可由INSERTINTO(table_name)SELECT语句激发,所以,插入许多行可能导致单个的触发器调用。上面讨论的涉及MXB的3类触发器都是针对影响单行的语句。因此,有必要考虑影响多行的语句,这里对MXB的INSERT触发器进行讨论。(1)可处理多行的MXB上的INSER
10、T触发器如果要进行多行插入,上面示例中的触发器可能就不能正确处理,因为UPDATE语句赋值表达式右边的表达式只能是一个值,而不能是一个值列表。因此,该触发器的作用就是获取inserted表中任意一行的值,并将其添加到JCB表中特定教材代码值的已有库存量值上。如果某个教材代码值在inserted表中出现了多次,则可能无法得到预期的结果。为了正确地更新JCB表,触发器就必须适应inserted表中出现多行的可能性。这可以通过SUM函数实现,它为inserted表中每个教材代码计算教材进出的总计。SUM函数存放于相关子查询中(SELECT语句在括号内)。该子查询为inserted表中与JCB表的教材
11、代码匹配或相关的每个教材代码返回一个单一值。CREATETRIGGERMXBINSEONdbo.MXBFORINSERTASUPDATEJCBSET库存量=库存量+(SELECTSUM(教材进-教材出)FROMINSERTEDWHEREJCB.教材代码=INSERTED.教材代码)WHEREJCB.教材代码IN(SELECT教材代码FROMINSERTED)该触发器对单行插入同样适用,不过,使用该触发器时,WHERE子句中所使用的相关子查询和IN运算符需要额外处理,而这对于单行插入来说是不必要的。(2)可区分单行和多行插入的MXB上的INSERT触发器可以通过系统函数ROWCOUNT以区分单行
12、插入和多行插入,以使触发器针对不同行数使用最优方法。CREATETRIGGERMXB_INSEONdbo.MXBFORINSERTASIFROWCOUNT=1BEGINUPDATEJCBSET库存量=库存量+(SELECT教材进-教材出FROMINSERTED)FROMJCB,INSERTEDWHEREJCB.教材代码=INSERTED.教材代码ENDELSEBEGINUPDATEJCBSET库存量=库存量+(SELECTSUM(教材进-教材出)FROMINSERTEDWHEREJCB.教材代码=INSERTED.教材代码)WHEREJCB.教材代码IN(SELECT教材代码FROMINSER
13、TED)END二、结论触发器应用于支持企业级商业解决方案时,是一个功能十分强大的工具。它可以用于实现业务规则,可以检查事务,可以在同一表上创建多个触发器来分离代码的功能。另外,通过使用触发器收集的信息,可以提高数据库的性能,可以用来维护那些使用外键所不能实现的复杂参数完整性。因此,对于维护数据表之间一致性,保持数据的相关完整性的情况,触发器应作为首先考虑的技术。储过程中返回结果从存储过程中返回结果有三种方式:1、返回结果集这是客户端应用程序返回结果的最通用的方法。结果集是通过使用SELECT语句选择数据产生的。结果集可以从永久表、临时表或局部变量中产生。将结果返回到另一个存储过程不是一种有效的
14、方法。存储过程不能访问另一个存储过程建立的结果集。例如从永久表中返回结果集:USEpubsGOCREATEPROCEDUREap_CreateResultFromPermtableASSELECTau_inameFROMauthorsGO例如从局部变量中创建结果集:USEpubsGOCREATEPROCEDUREap_CreateResultFromVariableASDECLAREau_inamechar(20)SELECTau_iname=au_inameFROMauthorsWHEREau_id=172-32-1176SELECTau_idGO2、设置OUTPUT参数的值输出参数经常用来
15、从存储过程中检索出结果。如果某个参数在传输到存储过程中时被定义成OUTPUT,则对该参数的任何修改在退出存储之后仍然有效。例如:USEpubsGOCREATEPROCEDUREap_SetOutputVarcountintegerOUTPUTASSELECTcount=count(*)FROMauthorsGO从输出参数中检索出值:USEpubsGOCREATEPROCEDUREap_GetOutputVarASDECLAREnumintegerEXECUTEap_SetOutputVarnumOUTPUTPRINT“thecountis”+convert(char,num)GO将游标使用成O
16、UTPUT参数。游标可以使用OUTPUT(输出)参数,但不能使用成输入参数。也就是说,游标可以作为结果返回,但却不能传输到过程中去。当游标被用作参数时,需要限定其为OUTPUT和VARYING。VARYING关键字指出该结果集要用来支持输出参数。这样就提供了将结果集返回到调用过程的能力。例如:USEpubsGOCREATEPROCEDUREGetTitleCountcount_cursorCURSORVARYINGOUTPUTASSETcount_cursor=CURSORFORSELECTau_id,count(*)FROMtitleauthorsGROUPBYau_idOPENcount_
17、cursorGO3、通过RETURN参数返回状态这是一种从存储过程返回错误码的方法。存储过程总是返回一个状态值,用户也可以使用RETURN语句返回自己的状态。例如:USEpubsGOCREATEPROCEDUREap_SetReturnStatusASDECLAREcountintegerSELECTcount=count(*)FROMauthorsIFcount=0RETURN(1)ELSERETURN(0)GO例如检索出返回的状态:USEpubsGOCREATEPROCEDUREap_GetReturnStatusASDECLAREstatusintegerEXECUTEstatus=ap
18、_SetReturnStatusIFstatus=1PRINT“Norowsfound”ELSEPRINT“successful”GO在存储过程中进行错误处理如同其它程序一样,在存储过程中进行错误处理是非常重要的。系统变更error在执行每一个TransactSQL语句之后都会得到一个值。对于成功的执行,error的值为0,如果出现错误,则error中将包含错误信息。error系统变量对存储过程的错误处理是非常重要的。注意:为了防止错误,error所能设置的值在sysmessages表的“error”中反映了出来。在存储过程中的错误有两种类型:1、数据库相关的错误这些错误是由数据库的不一致性引
19、起的,系统使用非0的error值表示特定的数据库问题。在TransactSQL执行之后,可以通过error获得所出现的错误。如果发现error不为0,则必须采取必要的行动,大多数情况下,存储将不再继续进行处理而返回。下面的示例展示了典型的获取数据库错误的方法。该过程将错误代码放置到输出变量中,这样,调用程序就能够访问到。USEpubsGOCREATEPROCEDUREap_TrapDatabaseErrorreturn_codeintegerOUTPUTASUPDATEauthorsSETau_iname=“Jackson”WHEREau_iname=“Smith”IFerror0BEGINS
20、ELECTreturn_code=errorRETURNENDELSEreturn_code=0GO2、业务逻辑错误这些错误是由于违反了业务规则而引起的。要获取这些错误,首先需要定义业务规则,基于这些规则,需要在存储过程中增加必要的错误检测代码。人们经常使用RAISERROR语句通报这些错误。RAISERROR提供了返回用户定义错误及将error变量设置成用户定义错误号的能力。错误消息可以被动态地建立,或者基于错误号从“sysmessages”表中检索到。一旦出现了错误,错误就会以一种服务器错误消息的方式返回到客户机。下面是RAISERROR命令的语法:RAISERROR(msg_id|msg
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 触发器 存储 过程 数据库 安全
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内