我正在尝试使用 SQL Server 中的 OPENJSON 从 JSON 文件构建规范化表。 JSON 的形式为:
{
"actions":[
{"action":"delete","table":"users","key":4}],
{"action":"update","table":"users","key":5,
"fields":[{"Name":"FirstName":,"OldValue":"X","NewValue":"Bob"},
{"Name":"LastName":,"OldValue":"Y","NewValue":"Dobbs"}]
}
我的目标是使用动态 SQL 中的这些条目来生成有效的查询:
UPDATE [users] SET [FirstName]='Bob',[LastName]='Dobbs' WHERE [key]=5
目前我正在使用这个SQL:
SELECT * FROM OPENJSON(@json, '$.actions')
WITH (
[Action] varchar(25) '$.action',
[Table] varchar(25) '$.table',
[Key] varchar(25) '$.key',
[fields] nvarchar(MAX) AS JSON
)
这给了我有用的结果,例如:
update users 5 {"name":...
我最初的想法是使用字符串解析来分解字段中的数据,但现在我意识到这是个坏主意。我相信我可以从临时表中查询出来并进入 JSON 解析器,并将其分解为行集,但我已经到处查看,但找不到显示这一点的示例。
有人对如何处理不同长度的字段列表有任何建议吗?
看起来您需要
OUTER APPLY
和 STRING_AGG
来突破并重新聚合 fields
属性。
DECLARE @json nvarchar(max) = N'{
"actions":[
{"action":"delete","table":"users","key":4},
{"action":"update","table":"users","key":5,
"fields":[{"Name":"FirstName","OldValue":"X","NewValue":"Bob"},
{"Name":"LastName","OldValue":"Y","NewValue":"Dobbs"}]
}
]}';
DECLARE @sql nvarchar(max);
SELECT @sql = STRING_AGG(
UPPER(j1.action) + QUOTENAME(j1.[table]) +
CASE WHEN j1.action = 'update'
THEN '
SET
' + updateFields.allCols
ELSE ''
END + '
WHERE [key] = ' +
j1.[key] +
';',
'
')
FROM OPENJSON(@json, '$.actions')
WITH (
action nvarchar(25),
[table] sysname,
[key] nvarchar(25),
fields nvarchar(MAX) AS JSON
) j1
OUTER APPLY (
SELECT STRING_AGG(
' ' + QUOTENAME(j2.Name) + ' = ' + ISNULL('N''' + REPLACE(j2.NewValue, '''', '''''') + '''', 'NULL'),
'
'
)
FROM OPENJSON(j1.fields)
WITH (
Name sysname,
NewValue nvarchar(max)
) j2
) updateFields(allCols);
PRINT @sql; -- your friend
EXEC sp_executesql @sql;