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_2507192051423391160 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_2507192051423391161;
INSERT INTO #PRODUCTTEMP
VALUES (@pMAIN_2507192051423391162, @pMAIN_2507192051423391163, @pMAIN_2507192051423391164, @pMAIN_2507192051423391165, @pMAIN_2507192051423391166),
(@pMAIN_2507192051423391167, @pMAIN_2507192051423391168, @pMAIN_2507192051423391169, @pMAIN_250719205142339116_10, @pMAIN_250719205142339116_11),
(@pMAIN_250719205142339116_12, @pMAIN_250719205142339116_13, @pMAIN_250719205142339116_14, @pMAIN_250719205142339116_15, @pMAIN_250719205142339116_16),
(@pMAIN_250719205142339116_17, @pMAIN_250719205142339116_18, @pMAIN_250719205142339116_19, @pMAIN_250719205142339116_20, @pMAIN_250719205142339116_21),
(@pMAIN_250719205142339116_22, @pMAIN_250719205142339116_23, @pMAIN_250719205142339116_24, @pMAIN_250719205142339116_25, @pMAIN_250719205142339116_26);
MERGE INTO #PRODUCTTEMP
AS Target
USING (VALUES (@pMAIN_250719205142339116_27, @pMAIN_250719205142339116_28, @pMAIN_250719205142339116_29, @pMAIN_250719205142339116_30, @pMAIN_250719205142339116_31), (@pMAIN_250719205142339116_32, @pMAIN_250719205142339116_33, @pMAIN_250719205142339116_34, @pMAIN_250719205142339116_35, @pMAIN_250719205142339116_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_2507192051423391160 |
the product name |
@pMAIN_2507192051423391161 |
1 |
@pMAIN_2507192051423391162 |
1 |
@pMAIN_2507192051423391163 |
Chai |
@pMAIN_2507192051423391164 |
18 |
@pMAIN_2507192051423391165 |
100 |
@pMAIN_2507192051423391166 |
0 |
@pMAIN_2507192051423391167 |
2 |
@pMAIN_2507192051423391168 |
Chang |
@pMAIN_2507192051423391169 |
19 |
@pMAIN_250719205142339116_10 |
17 |
@pMAIN_250719205142339116_11 |
0 |
@pMAIN_250719205142339116_12 |
3 |
@pMAIN_250719205142339116_13 |
Aniseed Syrup |
@pMAIN_250719205142339116_14 |
10 |
@pMAIN_250719205142339116_15 |
13 |
@pMAIN_250719205142339116_16 |
0 |
@pMAIN_250719205142339116_17 |
4 |
@pMAIN_250719205142339116_18 |
Ikura |
@pMAIN_250719205142339116_19 |
31 |
@pMAIN_250719205142339116_20 |
32 |
@pMAIN_250719205142339116_21 |
0 |
@pMAIN_250719205142339116_22 |
5 |
@pMAIN_250719205142339116_23 |
Pavlova |
@pMAIN_250719205142339116_24 |
17.45 |
@pMAIN_250719205142339116_25 |
29 |
@pMAIN_250719205142339116_26 |
0 |
@pMAIN_250719205142339116_27 |
78 |
@pMAIN_250719205142339116_28 |
New Gadget |
@pMAIN_250719205142339116_29 |
120.35 |
@pMAIN_250719205142339116_30 |
50 |
@pMAIN_250719205142339116_31 |
0 |
@pMAIN_250719205142339116_32 |
1 |
@pMAIN_250719205142339116_33 |
Chai |
@pMAIN_250719205142339116_34 |
18 |
@pMAIN_250719205142339116_35 |
10000 |
@pMAIN_250719205142339116_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_2507192051423710450 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_2507192051423710451;
INSERT INTO #PRODUCTTEMP
VALUES (@pMAIN_2507192051423710452, @pMAIN_2507192051423710453, @pMAIN_2507192051423710454, @pMAIN_2507192051423710455, @pMAIN_2507192051423710456),
(@pMAIN_2507192051423710457, @pMAIN_2507192051423710458, @pMAIN_2507192051423710459, @pMAIN_250719205142371045_10, @pMAIN_250719205142371045_11),
(@pMAIN_250719205142371045_12, @pMAIN_250719205142371045_13, @pMAIN_250719205142371045_14, @pMAIN_250719205142371045_15, @pMAIN_250719205142371045_16),
(@pMAIN_250719205142371045_17, @pMAIN_250719205142371045_18, @pMAIN_250719205142371045_19, @pMAIN_250719205142371045_20, @pMAIN_250719205142371045_21),
(@pMAIN_250719205142371045_22, @pMAIN_250719205142371045_23, @pMAIN_250719205142371045_24, @pMAIN_250719205142371045_25, @pMAIN_250719205142371045_26);
MERGE INTO #PRODUCTTEMP
AS Target
USING (VALUES (@pMAIN_250719205142371045_27, @pMAIN_250719205142371045_28, @pMAIN_250719205142371045_29, @pMAIN_250719205142371045_30, @pMAIN_250719205142371045_31), (@pMAIN_250719205142371045_32, @pMAIN_250719205142371045_33, @pMAIN_250719205142371045_34, @pMAIN_250719205142371045_35, @pMAIN_250719205142371045_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_2507192051423710450 |
the product name |
@pMAIN_2507192051423710451 |
1 |
@pMAIN_2507192051423710452 |
1 |
@pMAIN_2507192051423710453 |
Chai |
@pMAIN_2507192051423710454 |
18 |
@pMAIN_2507192051423710455 |
100 |
@pMAIN_2507192051423710456 |
0 |
@pMAIN_2507192051423710457 |
2 |
@pMAIN_2507192051423710458 |
Chang |
@pMAIN_2507192051423710459 |
19 |
@pMAIN_250719205142371045_10 |
17 |
@pMAIN_250719205142371045_11 |
0 |
@pMAIN_250719205142371045_12 |
3 |
@pMAIN_250719205142371045_13 |
Aniseed Syrup |
@pMAIN_250719205142371045_14 |
10 |
@pMAIN_250719205142371045_15 |
13 |
@pMAIN_250719205142371045_16 |
0 |
@pMAIN_250719205142371045_17 |
4 |
@pMAIN_250719205142371045_18 |
Ikura |
@pMAIN_250719205142371045_19 |
31 |
@pMAIN_250719205142371045_20 |
32 |
@pMAIN_250719205142371045_21 |
0 |
@pMAIN_250719205142371045_22 |
5 |
@pMAIN_250719205142371045_23 |
Pavlova |
@pMAIN_250719205142371045_24 |
17.45 |
@pMAIN_250719205142371045_25 |
29 |
@pMAIN_250719205142371045_26 |
0 |
@pMAIN_250719205142371045_27 |
78 |
@pMAIN_250719205142371045_28 |
New Gadget |
@pMAIN_250719205142371045_29 |
120.35 |
@pMAIN_250719205142371045_30 |
50 |
@pMAIN_250719205142371045_31 |
0 |
@pMAIN_250719205142371045_32 |
1 |
@pMAIN_250719205142371045_33 |
Chai |
@pMAIN_250719205142371045_34 |
18 |
@pMAIN_250719205142371045_35 |
10000 |
@pMAIN_250719205142371045_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_2507192051423910960, @pMAIN_2507192051423910961, @pMAIN_2507192051423910962, @pMAIN_2507192051423910963, @pMAIN_2507192051423910964, @pMAIN_2507192051423910965, @pMAIN_2507192051423910966), (@pMAIN_2507192051423910967, @pMAIN_2507192051423910968, @pMAIN_2507192051423910969, @pMAIN_250719205142391096_10, @pMAIN_250719205142391096_11, @pMAIN_250719205142391096_12, @pMAIN_250719205142391096_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_2507192051423910960 |
78 |
@pMAIN_2507192051423910961 |
New Gadget |
@pMAIN_2507192051423910962 |
1 |
@pMAIN_2507192051423910963 |
1 |
@pMAIN_2507192051423910964 |
100 |
@pMAIN_2507192051423910965 |
50 |
@pMAIN_2507192051423910966 |
0 |
@pMAIN_2507192051423910967 |
1 |
@pMAIN_2507192051423910968 |
Chai |
@pMAIN_2507192051423910969 |
1 |
@pMAIN_250719205142391096_10 |
1 |
@pMAIN_250719205142391096_11 |
18 |
@pMAIN_250719205142391096_12 |
50 |
@pMAIN_250719205142391096_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
|
|