2014-01-25 42 views
1

我将JSON作为参数传递给SQL存储过程。我使用了一个函数,它接收一个JSON字典并创建一个包含键值对(两列)的表,然后使用COALESCEINSERT语句创建动态SQL。这适用于单个字典,但我还需要能够发送包含字典数组的JSON字符串。现在,我的解析函数给了我这个表变量:支持动态列的TSQL表

enter image description here

我需要的是像这样的表变量:

enter image description here

我可以从第一个表中获取的列名与此:

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当前的回答结果: enter image description here

+0

我很确定parseJSON函数工作正常。它给了我一个包含所有键和值的SQL表。这个问题伴随着PIVOT部分。 –

+0

不要以为你完全明白我在说什么。你的parseJSON函数解析json字符串的方式没有什么不对。但是信息正在丢失,特别是密钥与哪个对象相关联。例子:'[{property1:'value1',property2:'value2'},{'property3':'value3'}]'和{[property1:'value1'},{'property2':'value2',property3 :'value3'}]'会在你的函数中产生相同的输出。那么你如何区分每个键属于哪个对象呢?唯一的方法是在函数中添加一个新列。它表示密钥属于哪个对象。 – Umair

+0

Gotcha。我将开始审查我正在使用的UDF。谢谢。 –

回答

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 

即动态旋转:)

编辑:

既然你不想通过在任何聚集我添加了一个行号函数来为每个不同的元素名分配一个顺序递增的id(基于元素值)。这将基本上将该透视图按该行列分组,从而生成所有必需的行。

+0

动态SQL不知道@JSONTable变量。我在我的问题中添加了我现在使用的SQL(包括您的建议)。 –

+0

啊是当然。你可以使用临时表吗? – Umair

+0

应该可以。让我试试 –