数据库教程:SQL Server中带有OUTPUT子句的INSERT,DELETE,UPDATE应用

output是sql server2005的新特性,可以从数据修改语句中返回输出,可以看作是"返回结果的dml"。insert、delete、update均支持output子句。在

output是sql server2005的新特性,可以从数据修改语句中返回输出,可以看作是"返回结果的dml"。

insert、delete、update均支持output子句。

在output子句中,可以引用特殊表inserted和deleted,使用inserted和deleted表与在触发器中使用的非常相似。

在insert,delete,update中output的区别

  • 对于insert,可以引用inserted表以查询新行的属性。
  • 对于delete,可以引用deleted表以查询旧行的属性。
  • 对于update,使用deleted表查询被更新行在更改前的属性,用inserted表标识被更新行在更改后的值。

输出方式:

  • 输出给调用方(客户端应用程序)
  • 输出给表

一、应用:

1、带有output的insert的应用

对于包含自增列的表执行多行insert语句,同时想知道新的标识值时,在insert中使用output子句非常方便。

1、对于单行insert语句,这不成问题:scope_identity函数即可实现。scope_identity函数:返回为当前会话和当前作用域中的任何表最后生成的标识值。

-- generating surrogate keys for customers    use tempdb;    go    if object_id('dbo.customersdim') is not null      drop table dbo.customersdim;    go      create table dbo.customersdim    (      keycol      int          not null identity primary key,      customerid  nchar(5)     not null,      companyname nvarchar(40) not null,      );      -- insert new customers and get their surrogate keys    declare @newcusts table    (      customerid nchar(5) not null primary key,      keycol     int      not null unique    );      insert into dbo.customersdim(customerid, companyname)           output inserted.customerid, inserted.keycol    into @newcusts        -- output inserted.customerid, inserted.keycol      select customerid, companyname  from northwind.dbo.customers    where country = n'uk';      select customerid, keycol from @newcusts;    go

注意代码中被注释掉的第二个output子句,后面没有into子句。如果还要输出返回给调用方,取消注释即可。这样insert语句将包含两个output子句。

2、多行insert语句

use adventureworks;    go     create table testtable (id int, textval varchar(100))      declare @tmptable table (id int, textval varchar(100))      insert testtable (id, textval)        output inserted.id, inserted.textval into @tmptable    values (1,'firstval')    insert testtable (id, textval)         output inserted.id, inserted.textval into @tmptable    values (2,'secondval')      select * from @tmptable    select * from testtable      drop table testtable    go

2、带有output的delete的应用.

如果要删除数据的同时,还需要记录日志,或者归档数据,在delete中使用output子句在适合不过了。

use adventureworks;    go      create table testtable (id int, textval varchar(100))  declare @tmptable table (id int, textval varchar(100))      insert testtable (id, textval)  values (1,'firstval')    insert testtable (id, textval)  values (2,'secondval')      delete  from testtable       output deleted.id, deleted.textval into @tmptable    where id in (1,2)      select * from @tmptable    select * from testtable      drop table testtable    go

3、带有output的update的应用

use adventureworks;    go      create table testtable (id int, textval varchar(100))      declare @tmptable table (id_new int, textval_new varchar(100),id_old int, textval_old varchar(100))      insert testtable (id, textval)  values (1,'firstval')    insert testtable (id, textval)  values (2,'secondval')      update testtable   set textval = 'newvalue'      output inserted.id, inserted.textval, deleted.id, deleted.textval into @tmptable    where id in (1,2)      select * from @tmptable    select * from testtable      drop table testtable    go

4、在 update 语句中使用包含 from_table_name 的 output into

以下示例使用指定的 productid 和 scrapreasonid,针对 workorder 表中的所有工作顺序更新 scrapreasonid 列。

output into 子句返回所更新表 (workorder) 中的值以及 product 表中的值。 在 product 子句中使用 from 表来指定要更新的行。

由于 workorder 表上定义了 after update 触发器,因此需要 into 关键字。

use adventureworks2012;  go    declare @mytestvar table (        oldscrapreasonid int not null,         newscrapreasonid int not null,         workorderid int not null,        productid int not null,        productname nvarchar(50)not null);        update production.workorder    set scrapreasonid = 4    output deleted.scrapreasonid,           inserted.scrapreasonid,            inserted.workorderid,           inserted.productid,           p.name        into @mytestvar    from production.workorder as wo        inner join production.product as p         on wo.productid = p.productid         and wo.scrapreasonid= 16        and p.productid = 733;        select oldscrapreasonid, newscrapreasonid, workorderid,         productid, productname     from @mytestvar;    go

4、merge语句

下面的示例捕获从 output 语句的 merge 子句返回的数据,并将这些数据插入另一个表。

merge 语句每天根据在 quantity 表中处理的订单更新 productinventory 表的 salesorderdetail 列。 如果产品的库存降至 0 或更低,它还会删除与这些产品对应的行。

本示例捕获已删除的行并将这些行插入另一个表 zeroinventory 中,该表跟踪没有库存的产品。

use adventureworks2012;    go    if object_id(n'production.zeroinventory', n'u') is not null        drop table production.zeroinventory;    go    --create zeroinventory table.    create table production.zeroinventory (deletedproductid int, removedondate datetime);    go        insert into production.zeroinventory (deletedproductid, removedondate)    select productid, getdate()    from    (   merge production.productinventory as pi        using (select productid, sum(orderqty) from sales.salesorderdetail as sod               join sales.salesorderheader as soh               on sod.salesorderid = soh.salesorderid               and soh.orderdate = '20070401'               group by productid) as src (productid, orderqty)        on (pi.productid = src.productid)        when matched and pi.quantity - src.orderqty <= 0            then delete        when matched            then update set pi.quantity = pi.quantity - src.orderqty        output $action, deleted.productid)   as changes (action, productid)    where action = 'delete';       if @@rowcount = 0    print 'warning: no rows were inserted';    go       select deletedproductid, removedondate from production.zeroinventory;

二、使用output子句的注意事项:

以下语句中不支持 output 子句:

  • 引用本地分区视图、分布式分区视图或远程表的 dml 语句。
  • 包含 execute 语句的 insert 语句。
  • 不能将 output into 子句插入视图或行集函数。
  • 参数或变量作为 update 语句的一部分进行了修改,则 output 子句将始终返回语句执行之前的参数或变量的值而不是已修改的值

三、c#中使用cmd.executescalar(单列)、cmdexecutereader(多行或多列)

返回单列:

using(sqlcommand cmd=new sqlcommand("insert into mem_basic(mem_na,mem_occ) output inserted.id values(@na,@occ)",con))      {          cmd.parameters.addwithvalue("@na", mem_na);          cmd.parameters.addwithvalue("@occ", mem_occ);          con.open();          int modified =(int)cmd.executescalar();          if (con.state == system.data.connectionstate.open)               con.close();         return modified;      }

返回多行或者多列:

create table suspension (pkey int not null identity(1, 1),  pallet_position int,  processing_pallet_pkey int,  datetime_created datetime,  datetime_updated datetime,  [this.created_by] int,  [this.updated_by] int);  using (var conn = new sqlconnection(connectionstring))  {      conn.open();      const string insertquery = @"  insert into dbo.suspension  (pallet_position, processing_pallet_pkey, datetime_created, datetime_updated,  [this.created_by], [this.updated_by])   output inserted.pkey values  (1, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2),   (2, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2),   (3, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2),   (4, 2, '20141013 16:27:25.000', '20141013 16:27:25.000', 2, 2);";        // 通过数据库      datatable dt = new datatable();      using (sqlcommand cmd = new sqlcommand(insertquery, conn))      using (var insertedoutput = cmd.executereader())      {          dt.load(insertedoutput);      }      console.writeline(dt.rows.count); // 4        // 通过手工读取      var list = new list<int>();      using (sqlcommand cmd = new sqlcommand(insertquery, conn))      using (var insertedoutput = cmd.executereader())      {          while(insertedoutput.read())          {              list.add(insertedoutput.getint32(0));          }      }      console.writeline(list.count); // 4        // 通过dapper      var ids = conn.query<int>(insertquery).tolist();      console.writeline(ids.count); // 4  }

四、参考:

https://docs.microsoft.com/zh-cn/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver15&viewfallbackfrom=sql-server-2014

以上就是数据库技术:SQL Server中带有OUTPUT子句的INSERT,DELETE,UPDATE应用的全部内容,希望对大家的学习有所帮助,也希望大家多多支持<计算机技术网(www.ctvol.com)!!>。

需要了解更多数据库技术:SQL Server中带有OUTPUT子句的INSERT,DELETE,UPDATE应用,都可以关注数据库技术分享栏目—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/dtteaching/1238426.html

(0)
上一篇 2022年9月11日
下一篇 2022年9月11日

精彩推荐