在SQL Server中查询json密钥名称

时间:2017-05-29 01:46:21

标签: sql-server json

鉴于json就是这样......

{"setting1":"A","setting2":"B","setting3":"C"}

我希望看到像...的结果

+----------+-------+
|   name   | value |
+----------+-------+
| setting1 | A     |
| setting2 | B     |
| setting3 | C     |
+----------+-------+

我的努力是试图找出如何提取密钥的名称(即"设置1","设置2"," setting3"等等。)

我可以执行类似以下查询的操作,但我不知道会有多少设置以及它们的名称,所以我想要更有活力的内容。

SELECT
    B.name,
    B.value
FROM OPENJSON(@json) WITH
    (
        setting1 varchar(50) '$.setting1',
        setting2 varchar(50) '$.setting2',
        setting3 varchar(50) '$.setting3'
    ) A
CROSS APPLY
    (
        VALUES
            ('setting1', A.setting1),
            ('setting2', A.setting2),
            ('setting3', A.setting3)
    ) B (name, value)

使用XML,我可以做这样简单的事情:

DECLARE @xml XML = '<settings><setting1>A</setting1><setting2>B</setting2><setting3>C</setting3></settings>'
SELECT
    A.setting.value('local-name(.)', 'VARCHAR(50)') name,
    A.setting.value('.', 'VARCHAR(50)') value
FROM @xml.nodes('settings/*') A (setting)

用SQL Server的json功能做任何类似的事情吗?

3 个答案:

答案 0 :(得分:2)

Aaron Bertrand在attribute directives

中写过关于json键值的文章
SELECT x.[Key], x.[Value] 
FROM OPENJSON(@Json, '$') AS x;

返回

Key         Value
------------------
setting1    A
setting2    B
setting3    C

答案 1 :(得分:0)

使用表格的选项

ID  Name        Value
1   setting1    A
1   setting2    B
1   setting3    C

<强>返回

Declare @String varchar(max) = '{"setting1":"A","setting2":"B","setting3":"C"}'

Select C.* 
 From  (values (try_convert(xml,replace(replace(replace(replace(replace(@String,'"',''),'{','<row '),'}','"/>'),':','="'),',','" '))) ) A (XMLData)
 Cross Apply (
                Select Name   = attr.value('local-name(.)','varchar(100)')
                      ,Value  = attr.value('.','varchar(max)') 
                 From  A.XMLData.nodes('/row') as C1(r)
                 Cross Apply C1.r.nodes('./@*') as C2(attr)
             ) C

使用字符串变量的选项

Name       Value
setting1    A
setting2    B
setting3    C

<强>返回

{{1}}

答案 2 :(得分:0)

如果您对TVF开放。

以下内容需要我的Extract UDF。创建此函数是因为我厌倦了提取字符串(patindex,charindex,left,right等)。它是一个修改的计数解析,它接受两个非类似的分隔符。

示例

Declare @YourTable table (ID int,JSON_String varchar(max))
Insert Into @YourTable values
 (1,'{"setting1":{"global":"A","type":"1"},"setting2":{"global":"B","type":"1"},"setting3":{"global":"C","type":"1"}} ')


Select A.ID
      ,B.Setting
      ,C.*
 From  @YourTable  A
 Cross Apply (
                Select Setting = replace(replace(B1.RetVal,'"',''),'{','')
                      ,B2.RetVal
                 From  [dbo].[udf-Str-Extract](A.JSON_String,',',':{') B1
                 Join  [dbo].[udf-Str-Extract](A.JSON_String,':{','}') B2
                   on  B1.RetSeq=B2.RetSeq
             ) B
 Cross Apply (
                Select Name  = C1.RetVal
                      ,Value = C2.RetVal
                 From  [dbo].[udf-Str-Extract](','+B.RetVal,',"','":') C1
                 Join  [dbo].[udf-Str-Extract](B.RetVal+',',':"','",') C2
                   on  C1.RetSeq=C2.RetSeq
             ) C

<强>返回

ID  Setting     Name    Value
1   setting1    global  A
1   setting1    type    1
1   setting2    global  B
1   setting2    type    1
1   setting3    global  C
1   setting3    type    1

感兴趣的UDF

CREATE FUNCTION [dbo].[udf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100))
Returns Table 
As
Return (  

with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
       cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A ),
       cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
       cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S)

Select RetSeq = Row_Number() over (Order By N)
      ,RetPos = N
      ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 
 From  (
        Select *,RetVal = Substring(@String, N, L) 
         From  cte4
       ) A
 Where charindex(@Delimiter2,RetVal)>1

)
/*
Max Length of String 1MM characters

Declare @String varchar(max) = 'Dear [[FirstName]] [[LastName]], ...'
Select * From [dbo].[udf-Str-Extract] (@String,'[[',']]')
*/