Help With Merge Statement I am wanting to compare the Distinct sn from HMI_Temp to sn in my table HMI -> if the sn exists, I want to update the values - got this syntax CHECK! - if the sn does NOT exist, I want to insert the data from HMI_Temp into HMI I have tried this syntax, but I get errors of:


  Invalid column name 'cb'
  Invalid column name 'lp'
  Invalid column name cn
  Invalid column name stn


And this is my syntax - how should I re-write this to accomplish my desired result?

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


This is the update statement I was using that worked, but now throwing a wrench in it for the insert if not exists :(

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
Here is at least a part of the problem: If you have two rows in HMI_Temp with the same value for sn but different values for cb (or any other column), which one should SQL Server pick?

Here is a better pattern than MERGE, IMHO, which has all kinds of issues:

INSERT dbo.HMI(stn,sn,cn,lp,cb)
SELECT stn,sn,cn,lp,cb
FROM
(
  SELECT stn,sn,cn,lp,cb,rn = ROW_NUMBER() OVER 
    (
      PARTITION BY sn,cn -- makes sn + cn distinct
      ORDER BY sID       -- picks which row to keep
    )
  FROM dbo.HMI_Temp
  WHERE NOT EXISTS 
  (
    SELECT 1 FROM dbo.HMI WHERE sn = hmi.sn
  )
) AS x
WHERE rn = 1;


This is taking the row with the lowest sID but you may wish to rank the rows a different way or use MIN/MAX on each of the other four columns to determine which row you want to keep. Hard to tell from your question.