设为首页 收藏本站
查看: 540|回复: 0

[经验分享] [学习SQL SERVER 2005系列]关于INSERT、UPDATE 或 DELETE的OUTPUT及OUTPUT...INTO...用法

[复制链接]

尚未签到

发表于 2016-11-10 05:14:33 | 显示全部楼层 |阅读模式

  • [学习SQLSERVER2005系列]关于INSERT、UPDATE或DELETE的OUTPUT及OUTPUT...INTO...用法
  •      作者:Flystone,转载注明出处

  • 在INSERT、UPDATE、DELETE语句中使用OUTPUT得到语句影响的每行信息,今天我们来学习这个语法。
  • 1、OUTPUT_CLAUSE定义(语法参Transact-SQL语法约定):

  • <OUTPUT_CLAUSE>::=
  • {
  • [OUTPUT<dml_select_list>INTO{@table_variable|output_table}[(column_list)]]
  • [OUTPUT<dml_select_list>]
  • }
  • <dml_select_list>::=
  • {<column_name>|scalar_expression}[[AS]column_alias_identifier]
  • [,...n]

  • <column_name>::=
  • {DELETED|INSERTED|from_table_name}.{*|column_name}

  • 2、OUTPUT_CLAUSE说明:
  • 返回受INSERT、UPDATE或DELETE语句影响的每行的信息,或者返回基于上述每行的表达式。这些结果可以返回到处理应用程序,以供在确认消息、存档以及其他类似的应用程序要求中使用。此外,也可以将结果插入表或表变量。

  • 3、典型应用:
  • 1、根据当前表的数据有条件的生成历史或新的初始化数据;
  • 2、把INSERT、UPDATE或DELETE语句影响的每行的信息暂存处理或反馈给应用程序完成业务或逻辑的完整性;
  • 3、OUTPUT子句对于在INSERT或UPDATE操作之后检索标识列或计算列的值可能非常有用;
  • 4、示列:
  • 1、根据当前表的数据有条件的生成历史数据;
  • 记得我以前做零售及水厂应用系统时都会有一个月未数据的处理功能,无非根据当前的数据自动生成下一个月数据的初始值。下面我以一个简化了例子来说明,例子是记录员工每个月工分变化中,我们以12月的数据生成下个月的月初数据。
  • ------------------------------------
  • --Author:happyflsytone
  • --Date:2008-10-0216:39:39
  • --Description:根据当前数据生成下个月的月初数据,并删除历史数据
  • ------------------------------------
  • DECLARE@sTABLE([年]INT,[月]INT,[工号]INT,[上月工分值]INT,[本月工分值]INT);

  • INSERT@sSELECT2008,12,1,10,11;
  • INSERT@sSELECT2008,12,2,11,12;
  • INSERT@sSELECT2008,12,3,11,13;
  • INSERT@sSELECT2008,12,4,3,5;
  • INSERT@sSELECT2008,12,5,1,7;
  • INSERT@sSELECT2008,12,6,2,11;


  • DELETEFROM@s
  • OUTPUTCASEWHENDELETED.[月]=12THENDELETED.[年]+1ELSEDELETED.[年]END,
  • CASEWHENDELETED.[月]=12THEN1ELSEDELETED.[月]+1END,
  • DELETED.[工号],DELETED.[本月工分值],NULLas[上月工分值]
  • INTO@s;
  • SELECT*
  • FROM@s
  • ORDERBY1,2,3
  • /*
  • 年月工号上月工分值本月工分值
  • -------------------------------------------------------
  • 20091111NULL
  • 20091212NULL
  • 20091313NULL
  • 2009145NULL
  • 2009157NULL
  • 20091611NULL

  • (6行受影响)

  • */


  • 2、根据业务规则的需要保证数据完整性。
  • 在这个例程里我假设在更新员工的最后登录时间同时增加一条日志信息。先看测试数据:
  • ------------------------------------
  • --Author:happyflsytone
  • --Date:2008-10-0216:39:39
  • --Description:员工登录时更新员工表的最后登录时间,同时在日志表增加一条登录信息
  • ------------------------------------
  • --操作员信息表(本例只关心最后登录时间,所以员工的信息不深入表述)
  • DECLARE@PTABLE([工号]INT,[姓名]varchar(16),[最后登录时间]datetime);

  • INSERT@PSELECT1,'test1',getdate()-1;
  • INSERT@PSELECT2,'test2',getdate()-1;
  • INSERT@PSELECT3,'test3',getdate()-1;
  • INSERT@PSELECT4,'test4',getdate()-1;
  • INSERT@PSELECT5,'test5',getdate()-1;
  • INSERT@PSELECT6,'test6',getdate()-1;
  • --操作员操作日志(象征性列举一些字段)
  • DECLARE@LOGTABLE([工号]INT,[操作时间]DATETIME,[操作类型]CHAR(6),[操作说明]VARCHAR(200));

  • --模拟工号为3的操作员登录,并记录相应日志
  • UPDATE@p
  • SET[最后登录时间]=GETDATE()
  • OUTPUTDELETED.[工号],DELETED.[最后登录时间],'出舱','成功出舱行走,身体状况良好,仪器工作正常,请主席放心!'
  • INTO@log
  • WHERE[工号]=3;

  • --查看日志

  • SELECT*
  • FROM@LOG;
  • /*
  • 工号操作时间操作类型操作说明
  • ----------------------------------------------------------------------------
  • 32008-10-0117:06:58.790出舱成功出舱行走,身体状况良好,仪器工作正常,请主席放心!
  • (1行受影响)
  • */

  • 注:其实我们可以通过这个OUTPUT_CLAUSE向应用程序提供数据操作的历史信息,或是把数据缓存在表变量中以备程序再次调用,关于这方面的例子就不多说明,因为这是最基本的OUTPUT_CLAUSE应用。

  • 3、标识列或计算列方面的应用
  • 对于标识列我们可能通过@@IDENTITY、SCOPE_IDENTITY和IDENT_CURRENT几个相似的函数获得,他们都返回插入到表的IDENTITY列的最后一个值(本身这几个函数还是有差异的,主要是它们的作用域,请查联机帮助)。我们注意到它们只是返回最后一个值,对于批量时就无能无力了。对于实时并发多的系统时我们可以利用OUTPUT_CLAUSE语句把标识列的值提取出来。

  • ------------------------------------
  • --Author:happyflsytone
  • --Date:2008-10-0216:39:39
  • ------------------------------------
  • CREATETABLEScrapReason(scrapreasonidINTIDENTITY,[name]VARCHAR(50),modifieddateDATETIME)
  • ;
  • --接受标识列值的表变量
  • DECLARE@MyTableVarTABLE(ScrapReasonIDSMALLINT,
  • NameVARCHAR(50),
  • ModifiedDateDATETIME);
  • --模拟插入数据
  • INSERTScrapReason
  • OUTPUTINSERTED.ScrapReasonID,INSERTED.Name,INSERTED.ModifiedDate
  • INTO@MyTableVar
  • SELECTN'OperatorIDENTITY',GETDATE()
  • FROMsys.objects;

  • --查看记录的标识列数据
  • SELECTScrapReasonID,Name,ModifiedDateFROM@MyTableVar;

  • GO
  • droptableScrapReason;
  • /*
  • ScrapReasonIDNameModifiedDate
  • --------------------------------------------------------------------------------------
  • 1OperatorIDENTITY2008-10-0217:42:19.000
  • 2OperatorIDENTITY2008-10-0217:42:19.000
  • 3OperatorIDENTITY2008-10-0217:42:19.000
  • 4OperatorIDENTITY2008-10-0217:42:19.000
  • 5OperatorIDENTITY2008-10-0217:42:19.000
  • 6OperatorIDENTITY2008-10-0217:42:19.000
  • .....
  • .....
  • 62OperatorIDENTITY2008-10-0217:42:19.000
  • 63OperatorIDENTITY2008-10-0217:42:19.000

  • (63行受影响)

  • */


  • 下面我们再来看看触发器使用OUTPUT_CLAUSE的情况,

  • ------------------------------------
  • --Author:happyflsytone
  • --Date:2008-10-0216:39:39
  • ------------------------------------
  • CREATETABLETA(
  • scrapreasonidINTIDENTITYPRIMARYKEY,
  • [name]VARCHAR(50),
  • modifieddateDATETIME
  • )
  • ;
  • CREATETABLETB(
  • IDINTREFERENCESTA(SCRAPREASONID),
  • [name]VARCHAR(50),
  • MODIFIEDDATEDATETIME
  • );
  • GO
  • CREATETRIGGERTR_INSERT
  • ONTA
  • INSTEADOFINSERT
  • AS
  • BEGIN
  • --接受标识列值的表变量
  • DECLARE@MyTableVarTABLE(IDINT,
  • [NAME]VARCHAR(10),
  • ModifiedDateDATETIME);
  • INSERTTA
  • OUTPUTINSERTED.scrapreasonid,INSERTED.[NAME],INSERTED.ModifiedDate
  • INTO@MyTableVar
  • SELECT[name],modifieddateFROMINSERTED
  • INSERTINTOTBSELECT*FROM@MyTableVar
  • END
  • GO

  • --模拟插入数据
  • INSERTTASELECT'TEST',GETDATE();
  • INSERTTASELECT'TEST2',GETDATE();

  • --查看记录的标识列数据
  • SELECT*FROMTB;


  • /*
  • IDnameMODIFIEDDATE
  • ------------------------------------------------------------------------------------
  • 1TEST2008-10-0217:53:46.780
  • 2TEST22008-10-0217:53:46.870

  • (2行受影响)

  • */
  • DROPTABLETB,TA;


  • 最后说明一下使用OUTPUT子句的注意事项:
  • 以下语句中不支持OUTPUT子句:

  • 1、引用本地分区视图、分布式分区视图或远程表的DML语句。
  • 2、包含EXECUTE语句的INSERT语句。
  • 3、不能将OUTPUTINTO子句插入视图或行集函数。
  • 4、参数或变量作为UPDATE语句的一部分进行了修改,则OUTPUT子句将始终返回语句执行之前的参数或变量的值而不是已修改的值



  • Flystone于常州

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-298044-1-1.html 上篇帖子: 遍例PHP中$_SERVER的服务器变量 下篇帖子: SQL Server学习笔记8之--关于OVER子句 多属性的比较 PIVOT 聚合问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表