Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
Azure SQL Database
Azure SQL Managed Instance
W instrukcji Transact-SQL UPDATE w natywnie skompilowanym module języka T-SQL następujące elementy składni nie są obsługiwane:
- Klauzula FROM
- Subqueries
Z kolei powyższe elementy są obsługiwane w natywnie skompilowanych modułach w instrukcji SELECT.
Instrukcje UPDATE z klauzulą FROM są często używane do aktualizowania informacji w tabeli na podstawie parametru wartości tabeli (TVP) lub aktualizowania kolumn w tabeli w wyzwalaczu AFTER.
Aby zapoznać się ze scenariuszem aktualizacji opartym na programie TVP, zobacz Implementowanie funkcji MERGE w natywnie skompilowanej procedurze składowanej.
Poniższy przykład ilustruje aktualizację wykonaną w wyzwalaczu. W tabeli kolumna o nazwie LastUpdated jest ustawiana na bieżącą datę i godzinę po dokonaniu aktualizacji. Obejście umożliwia wykonanie poszczególnych aktualizacji przy użyciu następujących elementów:
- Zmienna tabeli zawierająca kolumnę IDENTITY.
- Pętla WHILE do iterowania wierszy w zmiennej tabeli.
Oto oryginalna instrukcja T-SQL UPDATE:
UPDATE dbo.Table1
SET LastUpdated = SysDateTime()
FROM
dbo.Table1 t
JOIN Inserted i ON t.Id = i.Id;
Przykładowy kod T-SQL w poniższym bloku przedstawia obejście zapewniające dobrą wydajność. Tymczasowe rozwiązanie zostało zaimplementowane w natywnie skompilowanym wyzwalaczu. Kluczowe w kodzie są następujące elementy, na które należy zwrócić uwagę:
- Typ o nazwie dbo. Type1, czyli typ tabeli zoptymalizowany pod kątem pamięci.
- Pętla WHILE w wyzwalaczu.
- Pętla pobiera pojedynczo wiersze z Inserted.
DROP TABLE IF EXISTS dbo.Table1;
GO
DROP TYPE IF EXISTS dbo.Type1;
GO
-----------------------------
-- 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);
GO
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);
GO
----------------------------------------
-- 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
AS
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;
END
END
GO
---------------------------------
-- 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;
GO
Oto zestaw wyników.
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