Sql-Server
幫助合併聲明
我想比較表中的
Distinct sn
fromHMI_Temp
to -> 如果存在,我想更新值 - 得到這個語法檢查!- 如果不存在,我想將數據插入我已經嘗試過這種語法,但我收到以下錯誤:sn``HMI``sn``sn``HMI_Temp``HMI
無效的列名 ‘cb’
無效的列名 ’lp'
無效的列名 cn
無效的列名 stn
這是我的語法 - 我應該如何重寫它來實現我想要的結果?
MERGE INTO HMI AS Target USING (SELECT DISTINCT sn FROM HMI_Temp) AS Source ON Target.sn = Source.sn WHEN NOT MATCHED THEN INSERT (lp, cb, cn, sn, stn) VALUES (Source.lp, Source.cb, Source.cn, Source.sn, Source.stn);
DDL:
CREATE TABLE [dbo].[HMI_Temp] ( [sID] [int] IDENTITY(1,1) NOT NULL, stn [float] NULL, [sn] [nvarchar](255) NULL, [cn] [nvarchar](max) NULL, [lp] [nvarchar](max) NULL, [cb] [nvarchar](max) NULL, PRIMARY KEY CLUSTERED ( [sID] ASC ) WITH ( PAD_INDEX = OFF , STATISTICS_NORECOMPUTE = OFF , IGNORE_DUP_KEY = OFF , ALLOW_ROW_LOCKS = ON , ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO SET IDENTITY_INSERT [dbo].[HMI_Temp] ON GO INSERT [dbo].[HMI_Temp] ([sID], stn, [sn], [cn], [lp], [cb]) VALUES (1, 8888, N'Test', N'Test', N'Test123', N'Test456') VALUES (1, 8888, N'SecondTest', N'SecondTest', N'SecondTest123', N'SecondTest456') GO
這是我使用的更新語句,但如果不存在,現在將扳手放入其中以進行插入:(
UPDATE y SET y.lp = x.lp ,y.cb = x.cb ,y.cn = x.cn FROM HMI y INNER JOIN HMI_Temp x ON y.stn = x.stn AND y.sn = x.sn AND y.cn = x.cn
為了避免語法錯誤,您需要在
USING
子句中包含所有插入到目標表中的列。所以一個語法上有效的合併語句將是:MERGE INTO HMI AS Target USING (SELECT DISTINCT sn, lp, cb, cn, stn FROM HMI_Temp) AS Source ON Target.sn = Source.sn WHEN NOT MATCHED THEN INSERT (lp, cb, cn, sn, stn) VALUES (Source.lp, Source.cb, Source.cn, Source.sn, Source.stn);
由於您的預期功能包括更新現有行的能力,因此您還需要一個
WHEN MATCHED
子句,將目標表中的所需列設置為源表中的那些值。就像是:MERGE INTO HMI AS Target USING ( SELECT DISTINCT sn , lp , cb , cn , stn FROM HMI_Temp ) AS Source ON Target.sn = Source.sn WHEN MATCHED THEN UPDATE SET Target.lp = Source.lp , Target.cb = Source.cb , Target.cn = Source.cn , Target.stn = Source.stn WHEN NOT MATCHED THEN INSERT (lp, cb, cn, sn, stn) VALUES (Source.lp, Source.cb, Source.cn, Source.sn, Source.stn);
然而,正如 Aaron 在他的回答中提到的那樣,
MERGE
它充滿了其他潛在的問題。我使用了以下最低限度完整、可驗證的範例:
USE tempdb; DROP TABLE IF EXISTS dbo.HMI; CREATE TABLE dbo.HMI ( sID int IDENTITY(1,1) NOT NULL , stn float NULL , sn nvarchar(255) NULL , cn nvarchar(max) NULL , lp nvarchar(max) NULL , cb nvarchar(max) NULL , PRIMARY KEY CLUSTERED ( sID ASC ) WITH ( PAD_INDEX = OFF , STATISTICS_NORECOMPUTE = OFF , IGNORE_DUP_KEY = OFF , ALLOW_ROW_LOCKS = ON , ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]; GO INSERT dbo.HMI (stn, sn, cn, lp, cb) VALUES (8888, N'Test', N'Test', N'Test123', N'Test456') , (8887, N'A', N'B', N'C', N'D'); DROP TABLE IF EXISTS dbo.HMI_Temp; CREATE TABLE dbo.HMI_Temp ( sID int IDENTITY(1,1) NOT NULL , stn float NULL , sn nvarchar(255) NULL , cn nvarchar(max) NULL , lp nvarchar(max) NULL , cb nvarchar(max) NULL , PRIMARY KEY CLUSTERED ( sID ASC ) WITH ( PAD_INDEX = OFF , STATISTICS_NORECOMPUTE = OFF , IGNORE_DUP_KEY = OFF , ALLOW_ROW_LOCKS = ON , ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]; GO INSERT dbo.HMI_Temp (stn, sn, cn, lp, cb) VALUES (8888, N'Test', N'F', N'G', N'H')
數據如下:
SELECT * FROM dbo.HMI;
╔═════╦══════╦══════╦══════╦═════════╦═════════╗ ║ sID ║ stn ║ sn ║ cn ║ lp ║ cb ║ ╠═════╬══════╬══════╬══════╬═════════╬═════════╣ ║ 1 ║ 8888 ║ 測試 ║ 測試 ║ 測試123 ║ 測試456 ║ ║ 2 ║ 8887 ║ A ║ B ║ C ║ D ║ ╚═════╩══════╩══════╩══════╩═════════╩═════════╝
SELECT * FROM dbo.HMI_Temp;
╔═════╦══════╦══════╦════╦════╦════╗ ║ sID ║ stn ║ sn ║ cn ║ lp ║ cb ║ ╠═════╬══════╬══════╬════╬════╬════╣ ║ 1 ║ 8888 ║ 測試 ║ F ║ G ║ H ║ ╚═════╩══════╩══════╩════╩════╩════╝
合併聲明:
MERGE INTO dbo.HMI AS Target USING ( SELECT DISTINCT sn , lp , cb , cn , stn FROM dbo.HMI_Temp ) AS Source ON Target.sn = Source.sn WHEN MATCHED THEN UPDATE SET Target.lp = Source.lp , Target.cb = Source.cb , Target.cn = Source.cn , Target.stn = Source.stn WHEN NOT MATCHED THEN INSERT (lp, cb, cn, sn, stn) VALUES (Source.lp, Source.cb, Source.cn, Source.sn, Source.stn);
結果,發布
MERGE
:SELECT * FROM dbo.HMI;
╔═════╦══════╦══════╦════╦════╦════╗ ║ sID ║ stn ║ sn ║ cn ║ lp ║ cb ║ ╠═════╬══════╬══════╬════╬════╬════╣ ║ 1 ║ 8888 ║ 測試 ║ F ║ G ║ H ║ ║ 2 ║ 8887 ║ A ║ B ║ C ║ D ║ ╚═════╩══════╩══════╩════╩════╩════╝
如果
dbo.HMI_Temp
表包含非唯一行,如:INSERT dbo.HMI_Temp (stn, sn, cn, lp, cb) VALUES (8888, N'Test', N'F', N'G', N'H') , (8888, N'Test', N'I', N'J', N'K') , (8888, N'Test', N'L', N'M', N'N');
執行
MERGE
語句時,您會看到以下錯誤:消息 8672,級別 16,狀態 1,第 67 行
MERGE 語句多次嘗試更新或刪除同一行。當目標行匹配多個源行時會發生這種情況。MERGE 語句不能多次 UPDATE/DELETE 目標表的同一行。優化 ON 子句以確保目標行最多匹配一個源行,或使用 GROUP BY 子句對源行進行分組。
由於您現在已經澄清您還需要將
cn
列用作唯一性,您也許可以使用此合併語句:MERGE INTO dbo.HMI AS Target USING ( SELECT sn , lp , cb , cn , stn FROM dbo.HMI_Temp ) AS Source ON Target.sn = Source.sn AND Target.cn = Source.cn WHEN MATCHED THEN UPDATE SET Target.lp = Source.lp , Target.cb = Source.cb , Target.cn = Source.cn , Target.stn = Source.stn WHEN NOT MATCHED THEN INSERT (lp, cb, cn, sn, stn) VALUES (Source.lp, Source.cb, Source.cn, Source.sn, Source.stn);
注意,我添加
AND Target.cn = Source.cn
到WHERE
子句中。