如何使用SQL MERGE使用不同的子查询

时间:2015-02-19 09:41:02

标签: sql sql-server merge

我们可以在SQL MERGE中传递不同的子查询来插入和更新数据吗?

  MERGE TableA AS SOURCE
    USING TbaleB AS TARGET
    ON (SOURCE.ID=TARGET.ID) 
    WHEN NOT MATCHED BY TARGET  
    THEN INSERT(COLUMN1, COLUMN2,COLUMN3 ) 
        SELECT * FROM TableC
    WHEN MATCHED 
    THEN UPDATE COLUMN1=SOURCE.Column1, COLUMN2=SOURCE.Column2,COLUMN3=SOURCE.Column3
   FROM Table4  
   INNER JOIN INNER JOIN Table5
    ON  Table4.ID=Table5.ID
     WHERE Table5.ID=1

OUTPUT $action, inserted.*;

还有其他选择吗?

编辑: 使用下面的脚本创建表,插入数据,

CREATE TABLE TableA([ID] [int] IDENTITY(1,1) NOT NULL,
    ColumnA [nvarchar](50) NULL,
    ColumnB [nvarchar](50) NULL,
    ColumnC [nvarchar](50) NULL,    
) ON [PRIMARY]

CREATE TABLE TableB([ID] [int] IDENTITY(1,1) NOT NULL,
    ColumnA [nvarchar](50) NULL,
    ColumnB [nvarchar](50) NULL,
    ColumnC [nvarchar](50) NULL,    
) ON [PRIMARY]

Insert into TableA values('A','1','W')
Insert into TableA values('A','2','X')
Insert into TableA values('B','1','Y')
Insert into TableB values('A','1','U')--To be update
Insert into TableB values('B','2','N')--New row to insert

在查询下面使用以插入:

SELECT Source.* INTO #tempTable 
FROM (SELECT row_number() OVER ( PARTITION BY ColumnA,ColumnB ORDER BY ColumnA,ColumnB ) Row_ID, * --using row_number to remove duplicate rows
FROM  TableB) Source  
LEFT OUTER JOIN TableA Target 
ON  Source.ColumnA =  Target.ColumnA AND  Source.ColumnB =  Target.ColumnB 
WHERE Row_ID=1 AND Target.ColumnB IS NULL  AND Target.ColumnB IS NULL  
ALTER TABLE #tempTable drop column Row_ID, ID 

INSERT INTO TableA(ColumnA,ColumnB ,ColumnC) 
select * from #tempTable 

在查询下方用于更新现有记录:

UPDATE Target SET Target.ColumnC =Source.ColumnC
FROM TableA Target  
INNER JOIN TableB AS Source
ON  Source.ColumnA =  Target.ColumnA AND  Target.ColumnB =  SOURCE.ColumnB

我需要输出

ID  ColumnA ColumnB ColumnC
4   A   1   U
5   A   2   X
6   B   1   Y
7   B   2   N

它工作正常,但为了性能,我们可以使用MERGE做同样的事情吗?

1 个答案:

答案 0 :(得分:2)

尝试以下方法:

WITH S AS
(
    SELECT
        B.ColumnA, B.ColumnB, B.ColumnC
    FROM 
    (
        SELECT 
            B.ColumnA, B.ColumnB, B.ColumnC,
            ROW_NUMBER() OVER (PARTITION BY B.ColumnA, B.ColumnB ORDER BY B.ColumnA, B.ColumnB) AS RowId
        FROM TableB B
    ) B
    WHERE
        B.RowId = 1

)
MERGE 
    TableA T
USING 
    S ON T.ColumnA = S.ColumnA AND T.ColumnB = S.ColumnB
WHEN NOT MATCHED BY TARGET 
    THEN INSERT (ColumnA, ColumnB, ColumnC)
    VALUES (S.ColumnA, S.ColumnB, S.ColumnC)
WHEN MATCHED AND
     (S.ColumnC <> T.ColumnC OR S.ColumnC IS NULL AND T.ColumnC IS NOT NULL OR S.ColumnC IS NOT NULL AND T.ColumnC IS NULL)
     THEN UPDATE SET T.ColumnC = S.ColumnC;