以前只用过在insert完以后利用select @@IDENTITY返回主键ID,最近在做微信公众平台,遇到一个需求是在帮绑定万微信openid后自动完成登陆,这就需要update以后返回主键ID,查了一些资料找到了output这一解决方案。
update [SmartPromoter] set [Name]='aaaaaaaa' output DELETED.[ID] where [Mobile]='18669698888'
经测试,insert、update、delete都可以返回主键ID
查了一下msdn关于output的用法:以下为msdn上的用法
另外,您可以捕获嵌入的 INSERT、UPDATE、DELETE 或 MERGE 语句中 OUTPUT 子句的结果,然后将这些结果插入目标表或视图。
|
如果在运行语句的过程中出现任何错误,都不应使用该结果。 |
用在以下语句中:
|
当前版本),Azure SQL Database。 |
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 }
| $action
- @table_variable
-
必须在 INSERT、UPDATE、DELETE 或 MERGE 语句前声明。
column_list,则任何省略的列都必须允许 Null 值,或者都分配有默认值。
表 (Transact-SQL)。
- output_table
-
可以为临时表。
column_list,则任何省略的列都必须允许 Null 值,或者都分配有默认值。
无法应用于以下情况:
-
具有启用的对其定义的触发器。
-
参与 FOREIGN KEY 约束的任意一方。
-
具有 CHECK 约束或启用的规则。
-
- column_list
-
语句中允许使用的列列表。
- scalar_expression
-
中不允许使用聚合函数。
对修改的表中的列的任何引用都必须使用 INSERTED 或 DELETED 前缀限定。
- column_alias_identifier
-
用于引用列名的代替名称。
- DELETED
-
以 DELETED 为前缀的列反映了 UPDATE、DELETE 或 MERGE 语句完成之前的值。
不能在 INSERT 语句中同时使用 DELETED 与 OUTPUT 子句。
- INSERTED
-
以 INSERTED 为前缀的列反映了在 UPDATE、INSERT 或 MERGE 语句完成之后但在触发器执行之前的值。
INSERTED 语句不能与 DELETE 语句的 OUTPUT 子句同时使用。
- from_table_name
-
是一个列前缀,指定 DELETE、UPDATE 或 MERGE 语句(用于指定要更新或删除的行)的 FROM 子句中包含的表。
如果还在 FROM 子句中指定了要修改的表,则对该表中的列的任何引用都必须使用 INSERTED 或 DELETED 前缀限定。
- *
-
指定受删除、插入或更新操作影响的所有列都将按照它们在表中的顺序返回。
表中所有已删除的列:
DELETE Sales.ShoppingCartItem OUTPUT DELETED.*; - column_name
-
column_name。
- $action
-
类型的列,该子句为每行返回以下三个值之一:'INSERT'、'UPDATE' 或 'DELETE',返回哪个值取决于对该行执行的操作。
} 子句可以在单个 INSERT、UPDATE、DELETE 或 MERGE 语句中定义。
|
除非另行指定,否则,对 OUTPUT 子句的引用将同时引用 OUTPUT 子句和 OUTPUT INTO 子句。 |
OUTPUT 子句对于在 INSERT 或 UPDATE 操作之后检索标识列或计算列的值可能非常有用。
新列中的值是在执行该语句时计算出的值。
无法保证将更改应用于表的顺序与将行插入输出表或表变量的顺序相对应。
如果将参数或变量作为 UPDATE 语句的一部分进行了修改,则 OUTPUT 子句将始终返回语句执行之前的参数或变量的值而不是已修改的值。
在使用 WHERE CURRENT OF 语法通过游标定位的 UPDATE 或 DELETE 语句中,可以使用 OUTPUT。
以下语句中不支持 OUTPUT 子句:
-
引用本地分区视图、分布式分区视图或远程表的 DML 语句。
-
包含 EXECUTE 语句的 INSERT 语句。
-
当数据库兼容级别设置为 100 时,不允许在 OUTPUT 子句中使用全文谓词。
-
不能将 OUTPUT INTO 子句插入视图或行集函数。
-
如果用户定义的函数包含一个以表为目标的 OUTPUT INTO 子句,则不能创建该函数。
若要防止出现不确定的行为,OUTPUT 子句不能包含以下引用:
-
如果用户定义函数未绑定到架构,则认定它会执行数据访问。
-
视图或内嵌表值函数中的一个列(如果该列由以下方法之一定义):
-
子查询。
-
执行用户数据访问或系统数据访问或者被认为执行此种访问的用户定义函数。
-
定义中包含执行用户数据访问或系统数据访问的用户定义函数的计算列。
MSSQLSERVER_4186。
-
在捕获嵌套的 INSERT、UPDATE、DELETE 或 MERGE 语句中 OUTPUT 子句的结果并将这些结果插入目标表时,请牢记以下信息:
-
INSERT 语句和包含 OUTPUT 子句的嵌套 DML 语句要么都执行,要么整个语句都失败。
-
以下限制适用于外层 INSERT 语句的目标:
-
目标不能为远程表、视图或公用表表达式。
-
目标不能有 FOREIGN KEY 约束,或者被 FOREIGN KEY 约束所引用。
-
不能对目标定义触发器。
-
目标不能参与合并复制或事务复制的可更新订阅。
-
-
对于嵌套的 DML 语句有以下限制:
-
目标不能为远程表或分区视图。
-
源本身不能包含 <dml_table_source> 子句。
-
-
在包含 <dml_table_source> 子句的 INSERT 语句中不支持 OUTPUT INTO 子句。
-
@@ROWCOUNT 返回仅由外层 INSERT 语句插入的行。
-
@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 仅返回由嵌套的 DML 语句生成的标识值,而不返回由外层 INSERT 语句生成的标识值。
-
查询通知将语句作为单个实体进行处理,并且即使重大更改是来自外层 INSERT 语句本身,所创建的任何消息的类型也将是嵌套 DML 的类型。
-
在 <dml_table_source> 子句中,SELECT 和 WHERE 子句不能包括子查询、聚合函数、排名函数、全文谓词、执行数据访问的用户定义函数或是 TEXTPTR 函数。
从 OUTPUT 中返回的列反映 INSERT、UPDATE 或 DELETE 语句完成之后但在触发器执行之前的数据。
表,以免使用与 OUTPUT 关联的 INSERTED 和 DELETED 表复制列引用。
例如,如果在 UPDATE 语句中定义了 OUTPUT 子句,则目标表不能具有任何启用的 UPDATE 触发器。
disallow results from triggers,则从触发器内调用语句时,不带 INTO 子句的 OUTPUT 子句将导致该语句失败。
列的表达式的一部分出现。
以下示例在 DELETE 语句中使用 OUTPUT 子句将已删除的行返回到执行调用的应用程序。
USE AdventureWorks2012; GO DELETE TOP(1) dbo.DatabaseLog WITH (READPAST) OUTPUT deleted.* WHERE DatabaseLogID = 7; GO
列具有唯一性特征以实现所需的排序语义。
USE tempdb;
GO
CREATE TABLE dbo.table1
(
id INT,
employee VARCHAR(32)
);
GO
INSERT INTO dbo.table1 VALUES
(1, 'Fred')
,(2, 'Tom')
,(3, 'Sally')
,(4, 'Alice');
GO
DECLARE @MyTableVar TABLE
(
id INT,
employee VARCHAR(32)
);
PRINT 'table1, before delete'
SELECT * FROM dbo.table1;
DELETE FROM dbo.table1
OUTPUT DELETED.* INTO @MyTableVar
WHERE id = 4 OR id = 2;
PRINT 'table1, after delete'
SELECT * FROM dbo.table1;
PRINT '@MyTableVar, after delete'
SELECT * FROM @MyTableVar;
DROP TABLE dbo.table1;
--Results
--table1, before delete
--id employee
------------- ------------------------------
--1 Fred
--2 Tom
--3 Sally
--4 Alice
--
--table1, after delete
--id employee
------------- ------------------------------
--1 Fred
--3 Sally
--@MyTableVar, after delete
--id employee
------------- ------------------------------
--2 Tom
--4 Alice
|
这可防止在其他应用程序已经读取表中第一个限定记录的情况下出现锁定问题。 |
要求对通过 <dml_select_list> 检索的任何列或者在 <scalar_expression> 中使用的任何列具有 SELECT 权限。
要求对 <output_table> 中指定的任何表具有 INSERT 权限。
子句中返回由数据库引擎为该列生成的值。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO @MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO
表所执行的删除操作的结果。
USE AdventureWorks2012; GO DELETE Sales.ShoppingCartItem OUTPUT DELETED.* WHERE ShoppingCartID = 20621; --Verify the rows in the table matching the WHERE clause have been deleted. SELECT COUNT(*) AS [Rows in Table] FROM Sales.ShoppingCartItem WHERE ShoppingCartID = 20621; GO
变量。
表中更新操作的结果。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
变量。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
VacationHoursDifference int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.VacationHours - deleted.VacationHours,
inserted.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours,
VacationHoursDifference, ModifiedDate
FROM @MyTableVar;
GO
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
关键字。
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
子句中使用该表来指定要删除的行。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table (
ProductID int NOT NULL,
ProductName nvarchar(50)NOT NULL,
ProductModelID int NOT NULL,
PhotoID int NOT NULL);
DELETE Production.ProductProductPhoto
OUTPUT DELETED.ProductID,
p.Name,
p.ProductModelID,
DELETED.ProductPhotoID
INTO @MyTableVar
FROM Production.ProductProductPhoto AS ph
JOIN Production.Product as p
ON ph.ProductID = p.ProductID
WHERE p.ProductModelID BETWEEN 120 and 130;
--Display the results of the table variable.
SELECT ProductID, ProductName, ProductModelID, PhotoID
FROM @MyTableVar
ORDER BY ProductModelID;
GO
列的全部前像和后像。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table (
SummaryBefore nvarchar(max),
SummaryAfter nvarchar(max));
UPDATE Production.Document
SET DocumentSummary .WRITE (N'features',28,10)
OUTPUT deleted.DocumentSummary,
inserted.DocumentSummary
INTO @MyTableVar
WHERE Title = N'Front Reflector Bracket Installation';
SELECT SummaryBefore, SummaryAfter
FROM @MyTableVar;
GO
表中的值。
USE AdventureWorks2012;
GO
IF OBJECT_ID('dbo.vw_ScrapReason','V') IS NOT NULL
DROP VIEW dbo.vw_ScrapReason;
GO
CREATE VIEW dbo.vw_ScrapReason
AS (SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason);
GO
CREATE TRIGGER dbo.io_ScrapReason
ON dbo.vw_ScrapReason
INSTEAD OF INSERT
AS
BEGIN
--ScrapReasonID is not specified in the list of columns to be inserted
--because it is an IDENTITY column.
INSERT INTO Production.ScrapReason (Name, ModifiedDate)
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name,
INSERTED.ModifiedDate
SELECT Name, getdate()
FROM inserted;
END
GO
INSERT vw_ScrapReason (ScrapReasonID, Name, ModifiedDate)
VALUES (99, N'My scrap reason','20030404');
GO
语句中提供的值。
ScrapReasonID Name ModifiedDate
------------- ---------------- -----------------------
17 My scrap reason 2004-04-12 16:23:33.050
ProjectedSales)。
USE AdventureWorks2012 ;
GO
IF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL
DROP TABLE dbo.EmployeeSales;
GO
CREATE TABLE dbo.EmployeeSales
( EmployeeID int IDENTITY (1,5)NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL,
ProjectedSales AS CurrentSales * 1.10
);
GO
DECLARE @MyTableVar table(
EmployeeID int NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL,
ProjectedSales money NOT NULL
);
INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales)
OUTPUT INSERTED.LastName,
INSERTED.FirstName,
INSERTED.CurrentSales
INTO @MyTableVar
SELECT c.LastName, c.FirstName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%'
ORDER BY c.LastName, c.FirstName;
SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM @MyTableVar;
GO
SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM dbo.EmployeeSales;
GO
列以及行的删除日期和时间返回到执行调用的应用程序。
USE AdventureWorks2012;
GO
DECLARE @MyTableVar table (
ProductID int NOT NULL,
ProductName nvarchar(50)NOT NULL,
ProductModelID int NOT NULL,
PhotoID int NOT NULL);
DELETE Production.ProductProductPhoto
OUTPUT DELETED.ProductID,
p.Name,
p.ProductModelID,
DELETED.ProductPhotoID
INTO @MyTableVar
OUTPUT DELETED.ProductID, DELETED.ProductPhotoID, GETDATE() AS DeletedDate
FROM Production.ProductProductPhoto AS ph
JOIN Production.Product as p
ON ph.ProductID = p.ProductID
WHERE p.ProductID BETWEEN 800 and 810;
--Display the results of the table variable.
SELECT ProductID, ProductName, PhotoID, ProductModelID
FROM @MyTableVar;
GO
中,该表跟踪没有库存的产品。
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;