Friday, September 10, 2010

MERGE (Transact-SQL)

Question Suppose Table1 has following records:

id            emp        cellno
---------------------------------------------
1              abc         9999999995
2               xyz          9999999996

CREATE TABLE [dbo].[Table1](
      [id] [int] NULL,
      [employee] [nvarchar](50) NULL,
      [cellno] [nchar](10) NULL
) ON [PRIMARY]
GO

INSERT [dbo].[Table1] ([id], [employee], [cellno]) VALUES (1, N'abc', N'9868350985')
INSERT [dbo].[Table1] ([id], [employee], [cellno]) VALUES (1, N'xyz', N'9868350986')

And Table2 has following records:

id            emp        cellno
--------------------------------------------
1              abc         9319999995
3              tst            9868350987

CREATE TABLE [dbo].[Table2](
      [id] [int] NULL,
      [employee] [nvarchar](50) NULL,
      [cellno] [nchar](10) NULL
) ON [PRIMARY]
GO

INSERT [dbo].[Table2] ([id], [employee], [cellno]) VALUES (1, N'abc', N'9313164525')
INSERT [dbo].[Table2] ([id], [employee], [cellno]) VALUES (3, N'tst', N'9868350987')

Table2 contains the updated records for the employees.
Write the query that updates cellno for the employee in table1 if the record is already there else inserts the record in table1.i.e.
Running the query, records in table1 would be:

id            emp        cellno
---------------------------------------------
1              abc         9399999995
2              xyz           9999999996
3              tst            9868350987

Also I do not want to write 2 queries to achieve the desired output. There should be a single query.

Answer
MERGE Table1 AS Target
USING Table2 AS Source
ON (Target.id = Source.id)
--When records are matched, update the records if there is any change
WHEN MATCHED AND (Target.employee <> Source.employee OR Target.cellno <> Source.cellno) THEN
    UPDATE SET Target.employee = Source.employee, Target.cellno = Source.cellno
--When no records are matched, insert the incoming records from source table to target table
WHEN NOT MATCHED BY TARGET THEN
    INSERT (id, employee, cellno)
    VALUES (Source.id, Source.employee, Source.cellno)
--When there is a row that exists in target table and
--same record does not exist in source table
--then delete this record from target table
WHEN NOT MATCHED BY SOURCE THEN
DELETE
--$action specifies a column of type nvarchar(10)
--in the OUTPUT clause that returns one of three
--values for each row: 'INSERT', 'UPDATE', or 'DELETE',
--according to the action that was performed on that row
OUTPUT $action, Inserted.*, Deleted.*;

For more details about merge visit
http://technet.microsoft.com/en-us/library/bb510625.aspx

No comments:

Post a Comment