Rerunnable data update scripts for Microsoft SQL Server

Author: Steven Neiland
Published:

Last week I posted about how to write re-runnable data update scripts for MySQL/MariaDB for use with version control to manage data in lookup/reference tables.

Unfortunately the "INSERT IGNORE" solution to this problem is specific to MySQL/MariaDB and will not work for us on Microsoft's SQL Server.

Solution MERGE INTO

While SQL Server does not have a direct equivalent of INSERT IGNORE, we can achieve the same result with some work utilizing the MERGE INTO statement. This statement is simply more verbose, but can be broken into five parts.

Using our previous countries lookup table as an example:

1. Specify target table

MERGE INTO 
      dbo.countries AS tgt

2. Specify source data (Table or values)

Note that we need to name the columns in our data here as we are supplying the data directly instead of reading from a table.

USING( VALUES
      ( 1 , 'Afghanistan', 'AF' )
      ,( 2 , 'Albania', 'AL' )
      ,( 3 , 'Algeria', 'DZ' )
      ,( 4 , 'Andorra', 'AD' )
      ,( 5 , 'Angola', 'AO' )
) AS src (
      id
      , name
      , iso
)

3. Specify match condition

SQL Server will not assume to use the Primary Key so we explicitly specify the match condition

ON (tgt.id=src.id)

4. Match operation

If the match condition is met we define the update operation as follows

WHEN MATCHED THEN UPDATE SET
      tgt.name=src.name
      , tgt.iso=src.iso

5. Not Matched Operation

Finally we specify the insert operation for when the match condition is not met.

WHEN NOT MATCHED THEN INSERT (
      id
      , name
      , iso
) VALUES (
      src.id
      , src.name
      , src.iso
);

Final Solution

Putting these all together we get the following.

MERGE INTO 
      dbo.countries AS tgt
USING( VALUES
      ( 1 , 'Afghanistan', 'AF' )
      ,( 2 , 'Albania', 'AL' )
      ,( 3 , 'Algeria', 'DZ' )
      ,( 4 , 'Andorra', 'AD' )
      ,( 5 , 'Angola', 'AO' )
) AS src (
      id
      , name
      , iso
)
ON (tgt.id=src.id)
WHEN MATCHED THEN UPDATE SET
      tgt.name=src.name
      , tgt.iso=src.iso
WHEN NOT MATCHED THEN INSERT (
      id
      , name
      , iso
) VALUES (
      src.id
      , src.name
      , src.iso
);

Note: The terminating semi-colon is required.

Reader Comments

  • Please keep comments on-topic.
  • Please do not post unrelated questions or large chunks of code.
  • Please do not engage in flaming/abusive behaviour.
  • Comments that contain advertisments or appear to be created for the purpose of link building, will not be published.

Archives Blog Listing