适用于:
SQL Server
Azure SQL 数据库
Azure SQL 托管实例
在 Transact-SQL UPDATE 语句中,在本机编译的 T-SQL 模块中,不支持以下语法元素:
FROM 子句
与之相反,SELECT 语句上的本机编译模块支持前面的元素。
包含 FROM 子句的 UPDATE 语句通常用于基于表值参数 (TVP) 更新表格中的信息,或用于更新 AFTER 触发器的表格中的列。
请参阅
在本机编译的存储过程中实现 MERGE 功能
,了解基于 TVP 的更新方案。
下面的示例说明了在触发器中执行的更新。 在表中,名为 LastUpdated 的列设置为当前日期时间 AFTER 更新。 解决方法通过使用以下各项执行单个更新:
具有 IDENTITY 列的表变量。
循环访问表变量中的行的 WHILE 循环。
下面是原始的 T-SQL UPDATE 语句:
UPDATE dbo.Table1
SET LastUpdated = SysDateTime()
dbo.Table1 t
JOIN Inserted i ON t.Id = i.Id;
以下块中的示例 T-SQL 代码演示一个可提供良好性能的解决办法。 该解决办法在本机编译的触发器中实现。 对于该代码,需要注意的是:
名为 dbo.Type1 的类型,这是一种内存优化表类型。
触发器中的 WHILE 循环。
该循环从插入的行开始,一次检索一行。
DROP TABLE IF EXISTS dbo.Table1;
DROP TYPE IF EXISTS dbo.Type1;
-----------------------------
-- Table and table type.
-----------------------------
CREATE TABLE dbo.Table1
Id INT NOT NULL PRIMARY KEY NONCLUSTERED,
Column2 INT NOT NULL,
LastUpdated DATETIME2 NOT NULL DEFAULT (SYSDATETIME())
WITH (MEMORY_OPTIMIZED = ON);
CREATE TYPE dbo.Type1 AS TABLE
Id INT NOT NULL,
RowID INT NOT NULL IDENTITY,
INDEX ix_RowID HASH (RowID) WITH (BUCKET_COUNT=1024)
WITH (MEMORY_OPTIMIZED = ON);
----------------------------------------
-- Trigger that contains the workaround
-- for UPDATE with FROM.
----------------------------------------
CREATE TRIGGER dbo.tr_a_u_Table1
ON dbo.Table1
WITH NATIVE_COMPILATION, SCHEMABINDING
AFTER UPDATE
BEGIN ATOMIC WITH
TRANSACTION ISOLATION LEVEL = SNAPSHOT,
LANGUAGE = N'us_english'
DECLARE @tabvar1 dbo.Type1;
INSERT @tabvar1 (Id)
SELECT Id FROM Inserted;
DECLARE
@i INT = 1, @Id INT,
@max INT = SCOPE_IDENTITY();
---- Loop as a workaround to simulate a cursor.
---- Iterate over the rows in the memory-optimized table
---- variable and perform an update for each row.
WHILE @i <= @max
BEGIN
SELECT @Id = Id
FROM @tabvar1
WHERE RowID = @i;
UPDATE dbo.Table1
SET LastUpdated = SysDateTime()
WHERE Id = @Id;
SET @i += 1;
---------------------------------
-- Test to verify functionality.
---------------------------------
SET NOCOUNT ON;
INSERT dbo.Table1 (Id, Column2)
VALUES (1,9), (2,9), (3,600);
SELECT N'BEFORE-Update' AS [BEFORE-Update], *
FROM dbo.Table1
ORDER BY Id;
WAITFOR DELAY '00:00:01';
UPDATE dbo.Table1
SET Column2 += 1
WHERE Column2 <= 99;
SELECT N'AFTER--Update' AS [AFTER--Update], *
FROM dbo.Table1
ORDER BY Id;
-----------------------------
/**** Actual output:
BEFORE-Update Id Column2 LastUpdated
BEFORE-Update 1 9 2016-04-20 21:18:42.8394659
BEFORE-Update 2 9 2016-04-20 21:18:42.8394659
BEFORE-Update 3 600 2016-04-20 21:18:42.8394659
AFTER--Update Id Column2 LastUpdated
AFTER--Update 1 10 2016-04-20 21:18:43.8529692
AFTER--Update 2 10 2016-04-20 21:18:43.8529692
AFTER--Update 3 600 2016-04-20 21:18:42.8394659
****/