以逗号列表或类似形式返回数组?

问题描述 投票:0回答:1

我正在尝试在 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 解析器,并将其分解为行集,但我已经到处查看,但找不到显示这一点的示例。

有人对如何处理不同长度的字段列表有任何建议吗?

sql sql-server open-json
1个回答
0
投票

看起来您需要

OUTER APPLY
STRING_AGG
来突破并重新聚合
fields
属性。

另请注意

  • 使用
    sysname
    作为对象和列名称。
  • 使用
    QUOTENAME
    转义对象和列名称,使用
    REPLACE
    转义长字符串。
  • 我还没有考虑过
    INSERT
    ,但你应该能够适应这一点。
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] = ' +
    CAST(j1.[key] AS nvarchar(10)) +
    ';',
    '
  
')
FROM OPENJSON(@json, '$.actions')
  WITH (
    action nvarchar(25),
    [table] sysname,
    [key] int,
    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)
WHERE j1.action IN ('update', 'delete');

PRINT @sql;  -- your friend

EXEC sp_executesql @sql;

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.