SQL 使用 OPENJSON 的服务器存储过程:如何确定插入或更新?
SQL Server stored procedure with OPENJSON: How to determine insert or update?
这是我在 openjson
上的第一次尝试,我正在尝试设置一个存储过程来传递多条记录并将记录插入或更新到 table。我可以使用 openjson
设置基本的插入或更新查询,但我的问题是我不知道如何根据 json 值确定是否需要插入或更新当前记录。
这是一个简单的基本示例。我在 dbo.Orders
table.
中传入 json 数据和我想要 insert/update 的 2 个订单
我传入的第一个订单有OrderId = 123
,所以我知道记录已经存在,所以我需要更新它。然而,第二个订单有一个 OrderId = 0
。所以数据库中不存在这个,需要插入。
我该怎么做?
DECLARE @json NVARCHAR(2048) = N'[
{
"Order": {
"OrderId":123,
"Number":"SO43659",
"Date":"2011-05-31T00:00:00"
},
"AccountNumber":"AW29825",
"Item": {
"Price":2024.9940,
"Quantity":1
}
},
{
"Order": {
"Number":"SO43661",
"Date":"2011-06-01T00:00:00"
},
"AccountNumber":"AW73565",
"Item": {
"Price":2024.9940,
"Quantity":3
}
}
]'
SELECT * FROM OpenJson(@json);
--Here's where I need to do an insert/update. Not sure how, but here's the gist:
--If Json's Order.OrderId > 0
--BEGIN
-- UPDATE dbo.Orders WHERE OrderId = <Json's Order.OrderId>
--END
--ELSE
--BEGIN
-- INSERT INTO dbo.Orders (all values)
--END
感谢您的帮助
正如 Larnu 在他的评论中提到的,MERGE 就是您要找的东西。
这是您可以在 SSMS 中 运行 的示例:
DECLARE @json nvarchar(2048) = N'[
{"Order":{"OrderId":123,"Number":"SO43659","Date":"2011-05-31T00:00:00"},"AccountNumber":"AW29825","Item":{"Price":2024.9940,"Quantity":1}},
{"Order":{"Number":"SO43661","Date":"2011-06-01T00:00:00"},"AccountNumber":"AW73565","Item":{"Price":2024.9940,"Quantity":3}}
]';
/* ORDERS TABLE MOCK-UP */
DECLARE @Orders table (
OrderId int, OrderNumber varchar(10), OrderDate datetime, AccountNumber varchar(10), ItemPrice decimal(18,4), ItemQuantity int
);
/* INSERT A RECORD THAT WILL BE UPDATED BY THE MERGE */
INSERT INTO @Orders VALUES
( 123, 'SO43659', '2011-05-31 00:00:00.000', 'AW29825', 2024.9940, 5 ); -- Quantity will be updated to 1 via the MERGE.
/* SHOW ORDERS STARTING RESULTSET */
SELECT * FROM @Orders;
/* PERFORM ORDERS MERGE TO UPDATE/INSERT ROWS */
MERGE @Orders AS ord
USING (
SELECT * FROM OPENJSON( @json ) WITH (
OrderId int '$.Order.OrderId',
OrderNumber varchar(10) '$.Order.Number',
OrderDate datetime '$.Order.Date',
AccountNumber varchar(10) '$.AccountNumber',
ItemPrice decimal(18,4) '$.Item.Price',
ItemQuantity int '$.Item.Quantity'
)
) AS jsn
ON
ord.OrderId = jsn.OrderId
WHEN MATCHED THEN
UPDATE SET
OrderNumber = jsn.OrderNumber,
OrderDate = jsn.OrderDate,
AccountNumber = jsn.AccountNumber,
ItemPrice = jsn.ItemPrice,
ItemQuantity = jsn.ItemQuantity
WHEN NOT MATCHED THEN
INSERT ( OrderId, OrderNumber, OrderDate, AccountNumber, ItemPrice, ItemQuantity )
VALUES ( jsn.OrderId, jsn.OrderNumber, jsn.OrderDate, jsn.AccountNumber, jsn.ItemPrice, jsn.ItemQuantity );
/* SHOW THE MERGED RESULTSET */
SELECT * FROM @Orders;
@Orders
的初始结果集是:
+---------+-------------+-------------------------+---------------+-----------+--------------+
| OrderId | OrderNumber | OrderDate | AccountNumber | ItemPrice | ItemQuantity |
+---------+-------------+-------------------------+---------------+-----------+--------------+
| 123 | SO43659 | 2011-05-31 00:00:00.000 | AW29825 | 2024.9940 | 5 |
+---------+-------------+-------------------------+---------------+-----------+--------------+
执行 MERGE 后,更新的 @Orders
结果集为:
+---------+-------------+-------------------------+---------------+-----------+--------------+
| OrderId | OrderNumber | OrderDate | AccountNumber | ItemPrice | ItemQuantity |
+---------+-------------+-------------------------+---------------+-----------+--------------+
| 123 | SO43659 | 2011-05-31 00:00:00.000 | AW29825 | 2024.9940 | 1 |
| NULL | SO43661 | 2011-06-01 00:00:00.000 | AW73565 | 2024.9940 | 3 |
+---------+-------------+-------------------------+---------------+-----------+--------------+
您可以看到 MERGE
插入了 Number SO43661 的新记录并更新了 OrderId 123的ItemQuantity从5(它的初始值)到1.
这是我在 openjson
上的第一次尝试,我正在尝试设置一个存储过程来传递多条记录并将记录插入或更新到 table。我可以使用 openjson
设置基本的插入或更新查询,但我的问题是我不知道如何根据 json 值确定是否需要插入或更新当前记录。
这是一个简单的基本示例。我在 dbo.Orders
table.
我传入的第一个订单有OrderId = 123
,所以我知道记录已经存在,所以我需要更新它。然而,第二个订单有一个 OrderId = 0
。所以数据库中不存在这个,需要插入。
我该怎么做?
DECLARE @json NVARCHAR(2048) = N'[
{
"Order": {
"OrderId":123,
"Number":"SO43659",
"Date":"2011-05-31T00:00:00"
},
"AccountNumber":"AW29825",
"Item": {
"Price":2024.9940,
"Quantity":1
}
},
{
"Order": {
"Number":"SO43661",
"Date":"2011-06-01T00:00:00"
},
"AccountNumber":"AW73565",
"Item": {
"Price":2024.9940,
"Quantity":3
}
}
]'
SELECT * FROM OpenJson(@json);
--Here's where I need to do an insert/update. Not sure how, but here's the gist:
--If Json's Order.OrderId > 0
--BEGIN
-- UPDATE dbo.Orders WHERE OrderId = <Json's Order.OrderId>
--END
--ELSE
--BEGIN
-- INSERT INTO dbo.Orders (all values)
--END
感谢您的帮助
正如 Larnu 在他的评论中提到的,MERGE 就是您要找的东西。
这是您可以在 SSMS 中 运行 的示例:
DECLARE @json nvarchar(2048) = N'[
{"Order":{"OrderId":123,"Number":"SO43659","Date":"2011-05-31T00:00:00"},"AccountNumber":"AW29825","Item":{"Price":2024.9940,"Quantity":1}},
{"Order":{"Number":"SO43661","Date":"2011-06-01T00:00:00"},"AccountNumber":"AW73565","Item":{"Price":2024.9940,"Quantity":3}}
]';
/* ORDERS TABLE MOCK-UP */
DECLARE @Orders table (
OrderId int, OrderNumber varchar(10), OrderDate datetime, AccountNumber varchar(10), ItemPrice decimal(18,4), ItemQuantity int
);
/* INSERT A RECORD THAT WILL BE UPDATED BY THE MERGE */
INSERT INTO @Orders VALUES
( 123, 'SO43659', '2011-05-31 00:00:00.000', 'AW29825', 2024.9940, 5 ); -- Quantity will be updated to 1 via the MERGE.
/* SHOW ORDERS STARTING RESULTSET */
SELECT * FROM @Orders;
/* PERFORM ORDERS MERGE TO UPDATE/INSERT ROWS */
MERGE @Orders AS ord
USING (
SELECT * FROM OPENJSON( @json ) WITH (
OrderId int '$.Order.OrderId',
OrderNumber varchar(10) '$.Order.Number',
OrderDate datetime '$.Order.Date',
AccountNumber varchar(10) '$.AccountNumber',
ItemPrice decimal(18,4) '$.Item.Price',
ItemQuantity int '$.Item.Quantity'
)
) AS jsn
ON
ord.OrderId = jsn.OrderId
WHEN MATCHED THEN
UPDATE SET
OrderNumber = jsn.OrderNumber,
OrderDate = jsn.OrderDate,
AccountNumber = jsn.AccountNumber,
ItemPrice = jsn.ItemPrice,
ItemQuantity = jsn.ItemQuantity
WHEN NOT MATCHED THEN
INSERT ( OrderId, OrderNumber, OrderDate, AccountNumber, ItemPrice, ItemQuantity )
VALUES ( jsn.OrderId, jsn.OrderNumber, jsn.OrderDate, jsn.AccountNumber, jsn.ItemPrice, jsn.ItemQuantity );
/* SHOW THE MERGED RESULTSET */
SELECT * FROM @Orders;
@Orders
的初始结果集是:
+---------+-------------+-------------------------+---------------+-----------+--------------+
| OrderId | OrderNumber | OrderDate | AccountNumber | ItemPrice | ItemQuantity |
+---------+-------------+-------------------------+---------------+-----------+--------------+
| 123 | SO43659 | 2011-05-31 00:00:00.000 | AW29825 | 2024.9940 | 5 |
+---------+-------------+-------------------------+---------------+-----------+--------------+
执行 MERGE 后,更新的 @Orders
结果集为:
+---------+-------------+-------------------------+---------------+-----------+--------------+
| OrderId | OrderNumber | OrderDate | AccountNumber | ItemPrice | ItemQuantity |
+---------+-------------+-------------------------+---------------+-----------+--------------+
| 123 | SO43659 | 2011-05-31 00:00:00.000 | AW29825 | 2024.9940 | 1 |
| NULL | SO43661 | 2011-06-01 00:00:00.000 | AW73565 | 2024.9940 | 3 |
+---------+-------------+-------------------------+---------------+-----------+--------------+
您可以看到 MERGE
插入了 Number SO43661 的新记录并更新了 OrderId 123的ItemQuantity从5(它的初始值)到1.