Implementando a funcionalidade MERGE em um procedimento armazenado compilado de forma nativa
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure
O exemplo de código Transact-SQL nesta seção demonstra como você pode simular a instrução T-SQL MERGE em um módulo compilado de modo nativo. O exemplo usa uma variável de tabela com uma coluna de identidade, itera pelas linhas na variável da tabela e, para cada linha, executa a atualização se a condição corresponder e uma inserção se a condição não corresponder.
Veja a instrução MERGE T-SQL que você queria que fosse compatível em um proc nativo e que é simulada pelo exemplo de código.
MERGE INTO dbo.Table1 t
USING @tvp v
ON t.Column1 = v.c1
WHEN MATCHED THEN
UPDATE SET Column2 = v.c2
WHEN NOT MATCHED THEN
INSERT (Column1, Column2) VALUES (v.c1, v.c2);
Veja o T-SQL para obter a solução alternativa e simular MERGE.
DROP PROCEDURE IF EXISTS dbo.usp_merge1;
go
DROP TYPE IF EXISTS dbo.Type1;
go
DROP TABLE IF EXISTS dbo.Table1;
go
-----------------------------
-- target table and table type used for the workaround
-----------------------------
CREATE TABLE dbo.Table1
(
Column1 INT NOT NULL PRIMARY KEY NONCLUSTERED,
Column2 INT NOT NULL
)
WITH (MEMORY_OPTIMIZED = ON);
go
CREATE TYPE dbo.Type1 AS TABLE
(
c1 INT NOT NULL,
c2 INT NOT NULL,
RowID INT NOT NULL IDENTITY(1,1),
INDEX ix_RowID HASH (RowID) WITH (BUCKET_COUNT=1024)
)
WITH (MEMORY_OPTIMIZED = ON);
go
-----------------------------
-- stored procedure implementing the workaround
-----------------------------
CREATE PROCEDURE dbo.usp_merge1
@tvp1 dbo.Type1 READONLY
WITH
NATIVE_COMPILATION, SCHEMABINDING
AS
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT,
LANGUAGE = N'us_english')
DECLARE @i INT = 1, @c1 INT, @c2 INT;
WHILE @i > 0
BEGIN
SELECT @c1 = c1, @c2 = c2
FROM @tvp1
WHERE RowID = @i;
--test whether the row exists in the TVP; if not, we end the loop
IF @@ROWCOUNT=0
SET @i = 0
ELSE
BEGIN
-- try the update
UPDATE dbo.Table1
SET Column2 = @c2
WHERE Column1 = @c1;
-- if there was no row to update, we insert
IF @@ROWCOUNT=0
INSERT INTO dbo.Table1 (Column1, Column2)
VALUES (@c1, @c2);
SET @i += 1
END
END
END
go
-----------------------------
-- test to validate the functionality
-----------------------------
INSERT dbo.Table1 VALUES (1,2);
go
SELECT N'Before-MERGE' AS [Before-MERGE], Column1, Column2
FROM dbo.Table1;
go
DECLARE @tvp1 dbo.Type1;
INSERT @tvp1 (c1, c2) VALUES (1,33), (2,4);
EXECUTE dbo.usp_merge1 @tvp1;
go
SELECT N'After--MERGE' AS [After--MERGE], Column1, Column2
FROM dbo.Table1;
go
/**** Actual output:
Before-MERGE Column1 Column2
Before-MERGE 1 2
After--MERGE Column1 Column2
After--MERGE 1 33
After--MERGE 2 4
****/
Confira também
Problemas de migração para procedimentos armazenados compilados nativamente
Construções do Transact-SQL sem suporte pelo OLTP na memória