OUTPUT 子句

时间:2021-04-20 07:03:35

除了修改数据以外,一般不会希望修改语句后再做其他事情。也就是说,一般不会希望修改语句能够返回任何输出。然而,在有些场合下,能够从修改过的行中返回数据,这个功能可能也有一定的用处。

例如,考虑UPDATE语句,除了修改数据以外,对于发生更新的列,UPDATE 语句还可以返回这个列更新之前和更新之后的值。在排除问题、审核等其他情况下,这样的功能很有用处。

OUTPUT子句的考虑方式和SELECT子句非常像,也就是说,它们都是把想要返回的列或基于现有列的表达式依次列举出来。按照OUTPUT子句的语法,不同之处须要在列名之前加上inserted或deleted关键字。在INSERT语句中须要引用inserted,在DELETE语句中须要引用deleted。而在UPDATE语句中,如果需要更新前行的映像(image),则引用deleted;如果需要更新后行的映像,则引用inserted。

对于在OUTPUT子句中请求的各个属性,它会把来自修改过的各行中的相应值作为结果集而返回,这一点和SELECT语句的处理非常像。如果想把结果集导入另一个表,可以增加一个INTO子句,并提供目标表的名称。如果既想把修改过的行返回给调用者,又想把这些数据导入另一个表,则可以指定两个OUTPUT子句(一个有INTO子句,另一个没有)。

1.带有OUTPUT的INSERT语句

INSERT INTO dbo.T1(datacol)

  OUTPUT inserted.keycol,inserted.datacol

    SELECT dbo.Employees

    WHERE country=N'USA';

2.带有OUTPUT的DELETE语句

DELETE FROM dbo.Orders

  OUTPUT

    deleted.orderid,deleted.orderdate

  WHERE orderdate<'20080101'

如果想对被删除的各行进行归档,只要简单地增加一个INTO子句,并指定用于归档的表名作为其目标表。

3.带有OUTPUT的UPDATE语句

在UPDATE语句中使用 OUTPUT子句时,既可以通过将deleted关键字作为列名的前缀来引用被修改的行在发生变化之前的映像,也可以通过将inserted关键字作为列名的前缀来引用被修改的行在发生变化之后的映像。用这种方法就可以返回更新过的列的新、旧两个版本。

UPDATE dbo.OrderDetails

  SET discount=discount+0.05

OUTPUT

  inserted.productid,

  deleted.discount as olddiscount,

  inserted.discount as newdiscount

WHERE

  productid=51;

4.带有OUTPUT的MERGE语句

在MERGE语句中同样也可以使用OUTPUT子句,但要记得一个MERGE语句可以根据条件逻辑调用多个不同的DML操作。这意味着一个MERGE语句可能返回由不同DML操作生成的OUTPUT子句行。为了标识输出行由哪个DML操作生成,可以在OUTPUT子句中调用一个名为$action的函数,它会返回一个代表相应操作的字符串(“INSERT”、“UPDATE”及“DELETE”)。

MERGE INTO dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

  ON TGT.custid=SRC.custid

WHEN MATCHED THEN

  UPDATE SET

    TGT.companyname=SRC.companyname,

    TGT.phone=SRC.phone,

    TGT.address=SRC.address

  WHEN NOT MATCHED THEN

    INSERT(custid,companyname,phone,address)

    VALUES(SRC.custid,SRC.companyname,SRC.phone,SRC.address)

  OUTPUT

    $action,

    inserted.custid,

    deleted.companyname as oldcompanyname,

    inserted.companyname as newcompanyname