在SQL Server中,我有一个存储过程,该存储过程采用JSON参数@ChangeSet
,如下所示。
DECLARE @ChangeSet varchar(MAX) =
'{
"Acts":
[
{"ActId":100,"ActText":"Intro","ActNumber":1},
{"ActId":0, "ActText":"Beginning","ActNumber":2},
{"ActId":0, "ActText":"Middle","ActNumber":3},
{"ActId":0, "ActText":"End","ActNumber":4},
]
}';
在proc中,我有一个MERGE
语句,它根据是INSERT
(如果ActId
是0
)还是{{1} }。我想用UPDATE
的{{1}}表返回的多个PK ActId更新JSON @ChangeSet
变量,以便可以在INSERTED
参数中返回它。 / p>
MERGE
我可以重新查询数据库,将其输出为JSON,但有兴趣找出一种可能的方法,例如使用OUT
等直接更新JSON的技术。
我查看了各种样本,但没有发现任何类似的东西。有人有很好的例子吗?
答案 0 :(得分:1)
如果我对问题的理解正确,那么您有两种选择:
Acts
修改JSON_MODIFY
JSON数组(但您需要SQL Server 2017+才能将变量用作路径表达式)。这种方法在SELECT
语句中设置了局部变量,因此您不得在语句中使用ORDER BY
或DISTINCT
。FOR JSON AUTO
JSON:
DECLARE @ChangeSet varchar(MAX) =
'{
"Acts":
[
{"ActId":100,"ActText":"Intro","ActNumber":1},
{"ActId":0, "ActText":"Beginning","ActNumber":2},
{"ActId":0, "ActText":"Middle","ActNumber":3},
{"ActId":0, "ActText":"End","ActNumber":4}
]
}';
JSON_MODIFY
的声明:
SELECT @ChangeSet = JSON_MODIFY(
@ChangeSet,
CONCAT('$.Acts[', j1.[key], '].ActId'),
v.[Id]
)
FROM OPENJSON(@ChangeSet, '$.Acts') j1
CROSS APPLY OPENJSON(j1.[value]) WITH (ActNumber int '$.ActNumber') j2
JOIN (VALUES
(100, 'Act', 'UPDATE', 'Intro', 1),
(101, 'Act', 'INSERT', 'Beginning', 2),
(102, 'Act', 'INSERT', 'Middle', 3),
(103, 'Act', 'INSERT', 'End', 4)
) v ([Id], [Type], [Action], [Value], [ActNumber]) ON v.[ActNumber] = j2.[ActNumber]
FOR JSON
的声明:
SELECT @ChangeSet = (
SELECT v.[Id] AS ActId, j.ActText, j.ActNumber
FROM OPENJSON(@ChangeSet, '$.Acts') WITH (
ActId int '$.ActId',
ActText varchar(50) '$.ActText',
ActNumber int '$.ActNumber'
) j
JOIN (VALUES
(100, 'Act', 'UPDATE', 'Intro', 1),
(101, 'Act', 'INSERT', 'Beginning', 2),
(102, 'Act', 'INSERT', 'Middle', 3),
(103, 'Act', 'INSERT', 'End', 4)
) v ([Id], [Type], [Action], [Value], [ActNumber]) ON v.[ActNumber] = j.[ActNumber]
FOR JSON AUTO, ROOT ('Acts')
)
结果:
{
"Acts":
[
{"ActId":100, "ActText":"Intro", "ActNumber":1},
{"ActId":101, "ActText":"Beginning", "ActNumber":2},
{"ActId":102, "ActText":"Middle", "ActNumber":3},
{"ActId":103, "ActText":"End", "ActNumber":4}
]
}
答案 1 :(得分:0)
为完整起见,下面是完成的例程,该例程采用Merge语句的Output,将其插入到临时表变量中,然后使用新插入的ActId主键更新输入JSON,以便随后可以将其返回。过程OUT变量。
-- SQL 2017+ REQUIRED
DECLARE @ActActions table( [ActId] int, [Action] varchar(30),
[Value] nvarchar(max), [ActNumber] int );
---------------------------------------------------------------------------------
OUTPUT COALESCE (INSERTED.ActId, DELETED.ActId), $action,
COALESCE (INSERTED.ActText, DELETED.ActText),
COALESCE (INSERTED.ActNumber, DELETED.ActNumber)
INTO @ActActions; -- Required semi-colon at end of MERGE
---------------------------------------------------------------------------------
SELECT @ChangeSetJson = JSON_QUERY(JSON_MODIFY(
@ChangeSetJson, '$.Acts[' + j1.[key] + '].ActId', a.[ActId] ) )
FROM OPENJSON(@ChangeSetJson, '$.Acts') j1 CROSS APPLY
OPENJSON(j1.[value])
WITH (ActNumber int '$.ActNumber') j2 INNER JOIN
@ActActions a
ON a.[ActNumber] = j2.[ActNumber]
WHERE a.[Action] = 'INSERT'