SQL Smarties

SQL SMARTIES TIP13 T-SQL SEXY FEATURE The mythic UPSERT Or How to use MERGE

Aujourd’hui
Je suis frappée de voir à quel point les gens utilisent encore peu cette instruction dans leur pratique quotidienne. J’ai constaté que même si les gens passent d’une version à l’autre de SQL la pratique du T-SQL reste très minimaliste. Dans mes cartons j’ai un tableau avec par version les nouveautés qui DEVRAIENT être adoptées… Bon yapuka…

Autre note: ce tip a été “mailjunké” chez pas mal de cleints car j’avais utilisé le mot sexy …Pfffffffffffffffffffffffffffffffffff

SQL SMARTIES TIP13

T-SQL SEXY FEATURE: The mythic UPSERT Or How to use MERGE

                       

One of the most banal problem we have to resolve is the synchronization between tables and records.

And then we have the classical question :

Insert or Update? (the UPSERT well know pseudo code)

Does already exists my record in this table ?

So we test the existence and then we choose to make one of the both statement… Typically, this is done by executing a stored procedure or batch that contains individual INSERT, UPDATE, and DELETE statements. However, this means that the data in both the source and target tables are evaluated and processed multiple times; at least once for each statement.

USE AdventureWorks;

GO

CREATE PROCEDURE dbo.InsertUnitMeasure

@UnitMeasureCode nchar(3),

@Name nvarchar(25)

AS

BEGIN

SET NOCOUNT ON;

— Update the row if it exists.

UPDATE Production.UnitMeasure

SET Name = @Name

WHERE UnitMeasureCode = @UnitMeasureCode

— Insert the row if the UPDATE statement failed.

IF (@@ROWCOUNT = 0 )

BEGIN

INSERT INTO Production.UnitMeasure (UnitMeasureCode, Name)

VALUES (@UnitMeasureCode, @Name)

END

END;

GO

— Test the procedure and return the results.

EXEC InsertUnitMeasure @UnitMeasureCode = ‘ABC’, @Name = ‘Test Value’;

SELECT UnitMeasureCode, Name FROM Production.UnitMeasure

WHERE UnitMeasureCode = ‘ABC’;

GO

By using the MERGE statement, you can replace the individual DML statements with a single statement. This can improve query performance because the operations are performed within a single statement, therefore, minimizing the number of times the data in the source and target tables are processed.However, performance gains depend on having correct indexes, joins, and other considerations in place.

— perform the same operations using the MERGE statement.

ALTER PROCEDURE dbo.InsertUnitMeasure

@UnitMeasureCode nchar(3),

@Name nvarchar(25)

AS

BEGIN

SET NOCOUNT ON;

MERGE Production.UnitMeasure AS target

USING (SELECT @UnitMeasureCode, @Name) AS source (UnitMeasureCode, Name)

ON (target.UnitMeasureCode = source.UnitMeasureCode)—Join predicate

WHEN MATCHED THEN

UPDATE SET Name = source.Name

WHEN NOT MATCHED THEN

INSERT (UnitMeasureCode, Name)

VALUES (source.UnitMeasureCode, source.Name)

OUTPUT deleted.*, $action, inserted.* INTO #MyTempTable;

END;

GO

— Test the procedure and return the results.

EXEC InsertUnitMeasure @UnitMeasureCode = ‘ABC’, @Name = ‘New Test Value’;

EXEC InsertUnitMeasure @UnitMeasureCode = ‘XYZ’, @Name = ‘Test Value’;

EXEC InsertUnitMeasure @UnitMeasureCode = ‘ABC’, @Name = ‘Another Test Value’;

The source could be: variables, derived table, table , queries, Table Value Constructor (Transact-SQL)*

and so on…

We can also perfom a merge on this way

MERGE dbo.Fact_Generation as target

USING (SELECT day,quarter,generated_volume,generated_type FROM dbo.staging_generation) as source

ON (target.day = source.day AND target.quarter= source.quarter AND

target.generated_type_id=source.generated_type)

WHEN MATCHED THEN

UPDATE SET target.generated_volume = source.generated_volume

WHEN NOT MATCHED BY TARGET THEN

INSERT (day,quarter,generated_volume,generated_type_id )

VALUES (source.day,source.quarter,source.generated_volume,source.generated_type ) ;

For Massive Import Operation:

The MERGE statement can be used to efficiently bulk load data from a source data file (txt) into a target table by specifying the OPENROWSET(BULK…) clause as the table source. By doing so, the entire file is processed in a single batch.

On a  next tip I will discuss over the right choice between SSIS to import and synchronize data.

The whole syntax and examples in the BOL

Additionnal resources : http://msdn.microsoft.com/en-us/library/cc879317.aspx

*Table values constructor is a new T-SQL feature I will discuss in another tip.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s