我将JSON作为参数传递给SQL存储过程。我使用一个函数,它接受一个JSON字典并创建一个带有键值对(两列)的表,然后我使用COALESCE
为INSERT
语句创建动态sql。这适用于单个字典,但我还需要能够发送包含字典数组的JSON字符串。现在,我的解析函数给了我这个表变量:
我需要的是一个像这样的表变量:
我可以从第一个表中获取列名:
SELECT DISTINCT element name from @JSONTable
我应该提到这些元素名称可以而且会改变。我不知道不同的elementname值的数量。
更新 - 使用Umair的回答,我越来越近了:
DECLARE @JSONString AS VARCHAR(MAX)
SET @JSONString = '[{"ravid":3,"ravversion":2,"taskid":3},{"ravid":4,"ravversion":7,"taskid":99}]'
IF OBJECT_ID('tempdb..#JSONTable') IS NOT NULL
DROP TABLE #JSONTable
CREATE TABLE #JSONTable
(
elementname VARCHAR(500) ,
elementvalue VARCHAR(500)
)
INSERT INTO #JSONTable
( elementname ,
elementvalue
)
SELECT NAME ,
StringValue
FROM dbo.parseJSON(@JSONString)
WHERE LEN(StringValue) > 0 AND NAME IS NOT NULL
--declare a csv variable with all the distinct elements
DECLARE @csv NVARCHAR(max) = STUFF(
(
SELECT ',' + elementname
FROM (
SELECT DISTINCT elementname
FROM #JSONTable
) AS e
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(max)'),
1,
1,
''
);
DECLARE @sql NVARCHAR(MAX) = '
SELECT *
FROM (
SELECT *, Row = ROW_NUMBER() OVER (PARTITION BY elementname ORDER BY elementname)
FROM #JSONTable
) AS t
PIVOT (
MAX(elementvalue)
FOR elementname IN (' + @csv + ')
) AS p
'
EXEC sp_executesql @sql
但字典值并不对应于键。以下是Umair当前答案的结果:
答案 0 :(得分:0)
怎么样
--declare a csv variable with all the distinct elements
DECLARE @csv NVARCHAR(max) = STUFF(
(
SELECT ',' + elementname
FROM (
SELECT DISTINCT elementname
FROM #JSONTable
) AS e
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(max)'),
1,
1,
''
);
DECLARE @sql NVARCHAR(MAX) = '
SELECT *
FROM (
SELECT *, Row = ROW_NUMBER() OVER (PARTITION BY elementname ORDER BY elementvalue)
FROM #JSONTable
) AS t
PIVOT (
MAX(elementvalue)
FOR elementname IN (' + @csv + ')
) AS p
'
EXEC sp_executesql @sql
即动态旋转:)
编辑:
由于您不希望通过pivot中的任何内容进行聚合,因此我添加了一个行号函数,以便为每个不同的元素名分配一个顺序递增的id(基于元素值)。这将基本上按此行列对枢轴进行分组,从而生成所有必需的行。