Created
April 16, 2021 02:06
-
-
Save danielrothfus/687736dafca82289e6558b0333bd52ee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Generate a vanilla MERGE statement for Microsoft SQL Server that performs an | |
-- upsert. You may need to further modify the generated statement to fit your | |
-- needs, but it should at least save you from typing the same fields in | |
-- quadruplicate. | |
-- | |
-- History: | |
-- 2021-04-15: Daniel Rothfus - Initial version | |
DECLARE @MergeColumns TABLE([Name] SYSNAME NOT NULL); | |
INSERT INTO @MergeColumns | |
VALUES ('Key Column 1'), ('Key Column 2'); | |
DECLARE @TargetTable SYSNAME = 'TargetTable'; | |
DECLARE @Source NVARCHAR(MAX) = 'SourceTable'; | |
DECLARE @Command NVARCHAR(MAX); | |
WITH AllColumns AS ( | |
SELECT c.* | |
FROM sys.columns AS c | |
JOIN sys.objects AS o | |
ON c.object_id = o.object_id | |
WHERE o.name = @TargetTable | |
), AllQuotedColumnNames AS ( | |
SELECT QUOTENAME([name]) AS [Name] | |
FROM AllColumns | |
), UpdateColumnNamesQuoted AS ( | |
SELECT QUOTENAME([name]) AS [Name] | |
FROM AllColumns | |
WHERE [name] NOT IN ( | |
SELECT [Name] | |
FROM @MergeColumns | |
) | |
) | |
SELECT @Command = CONCAT( | |
-- See https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ for motivation behind HOLDLOCK | |
'MERGE INTO ', QUOTENAME(@TargetTable), ' WITH (HOLDLOCK) AS t ', CHAR(10), | |
'USING ', QUOTENAME(@Source), ' AS s', CHAR(10), | |
'ON ', ( | |
SELECT STRING_AGG(CONCAT('t.', QUOTENAME([Name]), ' = s.', QUOTENAME([Name])), CONCAT(CHAR(10), ' AND ')) | |
FROM @MergeColumns | |
), CHAR(10), | |
'WHEN MATCHED THEN UPDATE SET ', ( | |
SELECT STRING_AGG(CONCAT('t.', [Name], ' = s.', [Name]), CONCAT(',', CHAR(10), ' ')) | |
FROM UpdateColumnNamesQuoted | |
), CHAR(10), | |
'WHEN NOT MATCHED THEN INSERT (', CHAR(10), | |
( | |
SELECT STRING_AGG(CONCAT(' ', [Name]), CONCAT(', ', CHAR(10))) | |
FROM AllQuotedColumnNames | |
), CHAR(10), | |
') VALUES (', CHAR(10), | |
( | |
SELECT STRING_AGG(CONCAT(' s.', [Name]), CONCAT(', ', CHAR(10))) | |
FROM AllQuotedColumnNames | |
), CHAR(10), | |
')' | |
) | |
PRINT(@Command); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment