MERGE example


1. Update an existing product's UnitsInStock if it exists, otherwise insert a new product.

SQL Server Query 1

            
 -- Update an existing product's UnitsInStock if it exists, otherwise insert a new product.  
-- Create a temporary table to show MERGE
SELECT 1 AS ProductID, CAST('the product name' AS NVARCHAR(MAX)) AS ProductName,
CAST(0.00 AS money) AS UnitPrice, CAST(0 AS INT) AS UnitsInStock, CAST(0 AS bit) AS Discontinued
INTO #PRODUCTTEMP
-- Clear the temporary table
DELETE FROM #PRODUCTTEMP WHERE ProductID = 1
-- Inserts some value in temporary table
INSERT INTO #PRODUCTTEMP VALUES (1, 'Chai', 18.00, 100, 0),
(2, 'Chang', 19.00, 17, 0),
(3, 'Aniseed Syrup', 10.00, 13, 0),
(4, 'Ikura', 31.00, 32, 0),
(5, 'Pavlova', 17.45, 29, 0)

MERGE INTO #PRODUCTTEMP AS Target
USING (VALUES
(78, 'New Gadget', 120.35, 50, 0), -- New product (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued)
(1, 'Chai', 18.00, 10000, 0) -- Existing product (Chai - ProductID 1)
) AS Source (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued)
ON Target.ProductID = Source.ProductID
WHEN MATCHED THEN
UPDATE SET
Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock, -- Add to existing stock
Target.UnitPrice = Source.UnitPrice -- Update UnitPrice if changed
WHEN NOT MATCHED THEN
INSERT (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued)
VALUES (Source.ProductID, Source.ProductName, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);

SELECT * FROM #PRODUCTTEMP

DROP TABLE #PRODUCTTEMP

Create SQL query with SqlQueryBuilder 1

            
 var (sql1, parameters1) = new SqlQueryBuilder()  
.Select()
.Columns("ProductName", "MetricType", "MetricValue")
.From(new SqlQueryBuilder().Select()
.Columns("ProductID","ProductName","UnitsInStock","UnitsOnOrder")
.From("Products")
.Where(new Where(new Column("Discontinued").Equale(0))
.AND(new Column("UnitsInStock").GreaterThan(0))
.AND(new Column("ProductID").LessThan(30))), "SourceTable"
)
.UnPivot(new UnPivot(new Column("MetricValue"))
.For(new Column("MetricType")).IN("UnitsInStock", "UnitsOnOrder")
.TableName(new Table("UnpivotTable"))
)
.OrderBy(new OrderBy().SetColumnAscending("ProductName")
.SetColumnAscending("MetricType"))
.Build();

Query build by SqlQueryBuilder 1

            
SELECT CAST (1 AS INT) AS ProductID,
       CAST (@pMAIN_2603220327497547910 AS NVARCHAR (MAX)) AS ProductName,
       CAST (0.00 AS MONEY) AS UnitPrice,
       CAST (0 AS INT) AS UnitsInStock,
       CAST (0 AS BIT) AS Discontinued
INTO #PRODUCTTEMP;

DELETE #PRODUCTTEMP
WHERE ProductID = @pMAIN_2603220327497547911;

INSERT INTO #PRODUCTTEMP
VALUES (@pMAIN_2603220327497547912, @pMAIN_2603220327497547913, @pMAIN_2603220327497547914, @pMAIN_2603220327497547915, @pMAIN_2603220327497547916),
(@pMAIN_2603220327497547917, @pMAIN_2603220327497547918, @pMAIN_2603220327497547919, @pMAIN_260322032749754791_10, @pMAIN_260322032749754791_11),
(@pMAIN_260322032749754791_12, @pMAIN_260322032749754791_13, @pMAIN_260322032749754791_14, @pMAIN_260322032749754791_15, @pMAIN_260322032749754791_16),
(@pMAIN_260322032749754791_17, @pMAIN_260322032749754791_18, @pMAIN_260322032749754791_19, @pMAIN_260322032749754791_20, @pMAIN_260322032749754791_21),
(@pMAIN_260322032749754791_22, @pMAIN_260322032749754791_23, @pMAIN_260322032749754791_24, @pMAIN_260322032749754791_25, @pMAIN_260322032749754791_26);

MERGE INTO #PRODUCTTEMP
 AS Target
USING (VALUES (@pMAIN_260322032749754791_27, @pMAIN_260322032749754791_28, @pMAIN_260322032749754791_29, @pMAIN_260322032749754791_30, @pMAIN_260322032749754791_31), (@pMAIN_260322032749754791_32, @pMAIN_260322032749754791_33, @pMAIN_260322032749754791_34, @pMAIN_260322032749754791_35, @pMAIN_260322032749754791_36)) AS Source(ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued) ON Target.ProductID = Source.ProductID
WHEN MATCHED THEN UPDATE 
SET Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock,
    Target.UnitPrice    = Source.UnitPrice
WHEN NOT MATCHED THEN INSERT (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued) VALUES (Source.ProductID, Source.ProductName, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);

SELECT *
FROM #PRODUCTTEMP;

DROP TABLE #PRODUCTTEMP;


            
        

Parameters (If used)

Name Value
@pMAIN_2603220327497547910 the product name
@pMAIN_2603220327497547911 1
@pMAIN_2603220327497547912 1
@pMAIN_2603220327497547913 Chai
@pMAIN_2603220327497547914 18
@pMAIN_2603220327497547915 100
@pMAIN_2603220327497547916 0
@pMAIN_2603220327497547917 2
@pMAIN_2603220327497547918 Chang
@pMAIN_2603220327497547919 19
@pMAIN_260322032749754791_10 17
@pMAIN_260322032749754791_11 0
@pMAIN_260322032749754791_12 3
@pMAIN_260322032749754791_13 Aniseed Syrup
@pMAIN_260322032749754791_14 10
@pMAIN_260322032749754791_15 13
@pMAIN_260322032749754791_16 0
@pMAIN_260322032749754791_17 4
@pMAIN_260322032749754791_18 Ikura
@pMAIN_260322032749754791_19 31
@pMAIN_260322032749754791_20 32
@pMAIN_260322032749754791_21 0
@pMAIN_260322032749754791_22 5
@pMAIN_260322032749754791_23 Pavlova
@pMAIN_260322032749754791_24 17.45
@pMAIN_260322032749754791_25 29
@pMAIN_260322032749754791_26 0
@pMAIN_260322032749754791_27 78
@pMAIN_260322032749754791_28 New Gadget
@pMAIN_260322032749754791_29 120.35
@pMAIN_260322032749754791_30 50
@pMAIN_260322032749754791_31 0
@pMAIN_260322032749754791_32 1
@pMAIN_260322032749754791_33 Chai
@pMAIN_260322032749754791_34 18
@pMAIN_260322032749754791_35 10000
@pMAIN_260322032749754791_36 0

Query Results 1:

  ProductId ProductName UnitPrice UnitsInStock Discontinued
1 1 Chai 18.0000 10100 False
2 2 Chang 19.0000 17 False
3 3 Aniseed Syrup 10.0000 13 False
4 4 Ikura 31.0000 32 False
5 5 Pavlova 17.4500 29 False
6 78 New Gadget 120.3500 50 False


2. Update an existing product's UnitsInStock if it exists, otherwise insert a new product with table hints and insert without column names

SQL Server Query 2

            
 -- Update an existing product's UnitsInStock if it exists, otherwise insert a new product.  
-- Create a temporary table to show MERGE
SELECT 1 AS ProductID, CAST('the product name' AS NVARCHAR(MAX)) AS ProductName,
CAST(0.00 AS money) AS UnitPrice, CAST(0 AS INT) AS UnitsInStock, CAST(0 AS bit) AS Discontinued
INTO #PRODUCTTEMP
-- Clear the temporary table
DELETE FROM #PRODUCTTEMP WHERE ProductID = 1
-- Inserts some value in temporary table
INSERT INTO #PRODUCTTEMP VALUES (1, 'Chai', 18.00, 100, 0),
(2, 'Chang', 19.00, 17, 0),
(3, 'Aniseed Syrup', 10.00, 13, 0),
(4, 'Ikura', 31.00, 32, 0),
(5, 'Pavlova', 17.45, 29, 0)

MERGE INTO #PRODUCTTEMP WITH(ROWLOCK) AS Target
USING (VALUES
(78, 'New Gadget', 120.35, 50, 0), -- New product (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued)
(1, 'Chai', 18.00, 10000, 0) -- Existing product (Chai - ProductID 1)
) AS Source (ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued)
ON Target.ProductID = Source.ProductID
WHEN MATCHED THEN
UPDATE SET
Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock, -- Add to existing stock
Target.UnitPrice = Source.UnitPrice -- Update UnitPrice if changed
WHEN NOT MATCHED THEN
INSERT
VALUES (Source.ProductID, Source.ProductName, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);

SELECT * FROM #PRODUCTTEMP

DROP TABLE #PRODUCTTEMP

Create SQL query with SqlQueryBuilder 2

            
 var (sql2, parameters2) = new SqlQueryBuilder()  
.Select()
.Column(new CAST(new Column("1"), SqlDataType.INT), "ProductID")
.Column(new CAST(new Column().WithValue("the product name"), SqlDataType.NVARCHAR, "MAX"), "ProductName")
.Column(new CAST(new Column("0.00"), SqlDataType.MONEY), "UnitPrice")
.Column(new CAST(new Column("0"), SqlDataType.INT), "UnitsInStock")
.Column(new CAST(new Column("0"), SqlDataType.BIT), "Discontinued")
.INTO(new Table("#PRODUCTTEMP"))
.DeleteFrom("#PRODUCTTEMP").Where(new Where(new Column("ProductID").Equale(1)))
.InsertInto("#PRODUCTTEMP", new List<List<object>>() {
new List<object>() {1, "Chai", 18.00, 100, 0 },
new List<object>() {2, "Chang", 19.00, 17, 0},
new List<object>() {3, "Aniseed Syrup", 10.00, 13, 0},
new List<object>() {4, "Ikura", 31.00, 32, 0},
new List<object>() {5, "Pavlova", 17.45, 29, 0}
})
.Merge(new MERGE("#PRODUCTTEMP", new List<IHint>() { new NOLOCK() })
.AS("Target")
.USING_VALUES(new VALUES(new List<List<object>>()
{
new List<object>(){ 78, "New Gadget", 120.35, 50, 0 },
new List<object>(){ 1, "Chai", 18.00, 10000, 0 }
}, "Source", "ProductID", "ProductName", "UnitPrice", "UnitsInStock", "Discontinued"))
.ON(new Column("Target.ProductID").Equale(new Column("Source.ProductID")))
.WHEN_MATCHED_THEN(new SqlQueryBuilder()
.MergeUpdate(new List<ISetValue>()
{
new SetValue("Target.UnitsInStock", new ColumnArithmatic("Target.UnitsInStock").ADD("Source.UnitsInStock")),
new SetValue("Target.UnitPrice", new Column("Source.UnitPrice"))
})
)
.WHEN_NOT_MATCHED_THEN(new SqlQueryBuilder()
.MergeInsert(new List<IInsertValue>()
{
new InsertValue("ProductID", new Column("Source.ProductID")),
new InsertValue("ProductName", new Column("Source.ProductName")),
new InsertValue("UnitPrice", new Column("Source.UnitPrice")),
new InsertValue("UnitsInStock", new Column("Source.UnitsInStock")),
new InsertValue("Discontinued", new Column("Source.Discontinued")),
}, true)
)
)
.Select().Star().From("#PRODUCTTEMP")
.DropTable(new Table("#PRODUCTTEMP"))
.Build();

Query build by SqlQueryBuilder 2

            
SELECT CAST (1 AS INT) AS ProductID,
       CAST (@pMAIN_2603220327497948560 AS NVARCHAR (MAX)) AS ProductName,
       CAST (0.00 AS MONEY) AS UnitPrice,
       CAST (0 AS INT) AS UnitsInStock,
       CAST (0 AS BIT) AS Discontinued
INTO #PRODUCTTEMP;

DELETE #PRODUCTTEMP
WHERE ProductID = @pMAIN_2603220327497948561;

INSERT INTO #PRODUCTTEMP
VALUES (@pMAIN_2603220327497948562, @pMAIN_2603220327497948563, @pMAIN_2603220327497948564, @pMAIN_2603220327497948565, @pMAIN_2603220327497948566),
(@pMAIN_2603220327497948567, @pMAIN_2603220327497948568, @pMAIN_2603220327497948569, @pMAIN_260322032749794856_10, @pMAIN_260322032749794856_11),
(@pMAIN_260322032749794856_12, @pMAIN_260322032749794856_13, @pMAIN_260322032749794856_14, @pMAIN_260322032749794856_15, @pMAIN_260322032749794856_16),
(@pMAIN_260322032749794856_17, @pMAIN_260322032749794856_18, @pMAIN_260322032749794856_19, @pMAIN_260322032749794856_20, @pMAIN_260322032749794856_21),
(@pMAIN_260322032749794856_22, @pMAIN_260322032749794856_23, @pMAIN_260322032749794856_24, @pMAIN_260322032749794856_25, @pMAIN_260322032749794856_26);

MERGE INTO #PRODUCTTEMP
 AS Target
USING (VALUES (@pMAIN_260322032749794856_27, @pMAIN_260322032749794856_28, @pMAIN_260322032749794856_29, @pMAIN_260322032749794856_30, @pMAIN_260322032749794856_31), (@pMAIN_260322032749794856_32, @pMAIN_260322032749794856_33, @pMAIN_260322032749794856_34, @pMAIN_260322032749794856_35, @pMAIN_260322032749794856_36)) AS Source(ProductID, ProductName, UnitPrice, UnitsInStock, Discontinued) ON Target.ProductID = Source.ProductID
WHEN MATCHED THEN UPDATE 
SET Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock,
    Target.UnitPrice    = Source.UnitPrice
WHEN NOT MATCHED THEN INSERT VALUES (Source.ProductID, Source.ProductName, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);

SELECT *
FROM #PRODUCTTEMP;

DROP TABLE #PRODUCTTEMP;


            
        

Parameters (If used)

Name Value
@pMAIN_2603220327497948560 the product name
@pMAIN_2603220327497948561 1
@pMAIN_2603220327497948562 1
@pMAIN_2603220327497948563 Chai
@pMAIN_2603220327497948564 18
@pMAIN_2603220327497948565 100
@pMAIN_2603220327497948566 0
@pMAIN_2603220327497948567 2
@pMAIN_2603220327497948568 Chang
@pMAIN_2603220327497948569 19
@pMAIN_260322032749794856_10 17
@pMAIN_260322032749794856_11 0
@pMAIN_260322032749794856_12 3
@pMAIN_260322032749794856_13 Aniseed Syrup
@pMAIN_260322032749794856_14 10
@pMAIN_260322032749794856_15 13
@pMAIN_260322032749794856_16 0
@pMAIN_260322032749794856_17 4
@pMAIN_260322032749794856_18 Ikura
@pMAIN_260322032749794856_19 31
@pMAIN_260322032749794856_20 32
@pMAIN_260322032749794856_21 0
@pMAIN_260322032749794856_22 5
@pMAIN_260322032749794856_23 Pavlova
@pMAIN_260322032749794856_24 17.45
@pMAIN_260322032749794856_25 29
@pMAIN_260322032749794856_26 0
@pMAIN_260322032749794856_27 78
@pMAIN_260322032749794856_28 New Gadget
@pMAIN_260322032749794856_29 120.35
@pMAIN_260322032749794856_30 50
@pMAIN_260322032749794856_31 0
@pMAIN_260322032749794856_32 1
@pMAIN_260322032749794856_33 Chai
@pMAIN_260322032749794856_34 18
@pMAIN_260322032749794856_35 10000
@pMAIN_260322032749794856_36 0

Query Results 2:

  ProductId ProductName UnitPrice UnitsInStock Discontinued
1 1 Chai 18.0000 10100 False
2 2 Chang 19.0000 17 False
3 3 Aniseed Syrup 10.0000 13 False
4 4 Ikura 31.0000 32 False
5 5 Pavlova 17.4500 29 False
6 78 New Gadget 120.3500 50 False


3. Merge with Products table (Transcation is rollbacked)

SQL Server Query 3

            
 BEGIN TRANSACTION  
MERGE Products AS Target
USING (VALUES
(78, 'New Gadget', 1, 1, 100, 50, 0), -- New product (ProductID, ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, Discontinued)
(1, 'Chai', 1, 1, 18.00, 50, 0) -- Existing product (Chai - ProductID 1)
) AS Source (ProductID, ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, Discontinued)
ON Target.ProductID = Source.ProductID -- Match condition
WHEN MATCHED THEN
UPDATE SET
Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock, -- Add to existing stock
Target.UnitPrice = Source.UnitPrice -- Update UnitPrice if changed;
WHEN NOT MATCHED THEN
INSERT (ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, Discontinued)
VALUES (Source.ProductName, Source.SupplierID, Source.CategoryID, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);
SELECT TOP 5 * FROM Products
ROLLBACK TRANSACTION

Create SQL query with SqlQueryBuilder 3

            
 var (sql3, parameters3) = new SqlQueryBuilder()  
.Merge(new MERGE("Products")
.AS("Target")
.USING_VALUES(new VALUES(new List<List<object>>()
{
new List<object>() { 78, "New Gadget", 1, 1, 100, 50, 0 },
new List<object>() { 1, "Chai", 1, 1, 18.00, 50, 0 }
}, "Source", "ProductID", "ProductName", "SupplierID", "CategoryID", "UnitPrice", "UnitsInStock", "Discontinued"))
.ON(new Column("Target.ProductID").Equale(new Column("Source.ProductID")))
.WHEN_MATCHED_THEN(new SqlQueryBuilder()
.MergeUpdate(new List<ISetValue>()
{
new SetValue("Target.UnitsInStock", new ColumnArithmatic("Target.UnitsInStock").ADD("Source.UnitsInStock")),
new SetValue("Target.UnitPrice", new Column("Source.UnitPrice"))
})
)
.WHEN_NOT_MATCHED_THEN(new SqlQueryBuilder()
.MergeInsert(new List<IInsertValue>()
{
new InsertValue("ProductName", new Column("Source.ProductName")),
new InsertValue("SupplierID", new Column("Source.SupplierID")),
new InsertValue("CategoryID", new Column("Source.CategoryID")),
new InsertValue("UnitPrice", new Column("Source.UnitPrice")),
new InsertValue("UnitsInStock", new Column("Source.UnitsInStock")),
new InsertValue("Discontinued", new Column("Source.Discontinued")),
})
)
)
.Select().Top(5).Star().From("Products")
.Build();

Query build by SqlQueryBuilder 3

            
MERGE INTO Products
 AS Target
USING (VALUES (@pMAIN_2603220327498146810, @pMAIN_2603220327498146811, @pMAIN_2603220327498146812, @pMAIN_2603220327498146813, @pMAIN_2603220327498146814, @pMAIN_2603220327498146815, @pMAIN_2603220327498146816), (@pMAIN_2603220327498146817, @pMAIN_2603220327498146818, @pMAIN_2603220327498146819, @pMAIN_260322032749814681_10, @pMAIN_260322032749814681_11, @pMAIN_260322032749814681_12, @pMAIN_260322032749814681_13)) AS Source(ProductID, ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, Discontinued) ON Target.ProductID = Source.ProductID
WHEN MATCHED THEN UPDATE 
SET Target.UnitsInStock = Target.UnitsInStock + Source.UnitsInStock,
    Target.UnitPrice    = Source.UnitPrice
WHEN NOT MATCHED THEN INSERT (ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock, Discontinued) VALUES (Source.ProductName, Source.SupplierID, Source.CategoryID, Source.UnitPrice, Source.UnitsInStock, Source.Discontinued);

SELECT TOP 5 *
FROM Products;


            
        

Parameters (If used)

Name Value
@pMAIN_2603220327498146810 78
@pMAIN_2603220327498146811 New Gadget
@pMAIN_2603220327498146812 1
@pMAIN_2603220327498146813 1
@pMAIN_2603220327498146814 100
@pMAIN_2603220327498146815 50
@pMAIN_2603220327498146816 0
@pMAIN_2603220327498146817 1
@pMAIN_2603220327498146818 Chai
@pMAIN_2603220327498146819 1
@pMAIN_260322032749814681_10 1
@pMAIN_260322032749814681_11 18
@pMAIN_260322032749814681_12 50
@pMAIN_260322032749814681_13 0

Query Results 3:

  ProductID ProductName SupplierID CategoryID QuantityPerUnit UnitPrice UnitsInStock UnitsOnOrder ReorderLevel Discontinued StockLevelStars ProductDetailsWithTabs ProductName1 ProductName2 ProductSoundexDifference FormattedProductInfo
1 1 Chai 1 1 10 boxes x 20 bags 18.0000 89 0 10 False 0
2 2 Chang 1 1 24 - 12 oz bottles 19.0000 17 40 25 False 0
3 3 Aniseed Syrup 1 2 12 - 550 ml bottles 10.0000 13 70 25 False 0
4 4 Chef Anton's Cajun Seasoning 2 2 48 - 6 oz jars 22.0000 53 0 0 False 0
5 5 Chef Anton's Gumbo Mix 2 2 36 boxes 21.3500 0 0 0 True 0