如何使用列值作为节点将表数据转换为SQL Server中的JSON值?

时间:2017-11-22 07:18:26

标签: sql json sql-server

嗨,我是JSONSQL server进程的新手。

这是我的表:

DECLARE @Example TABLE 
    (
    ThirdPartyInterfaceData VARCHAR(10)
    ,ThirdPartyInterfaceName VARCHAR(10)
    ,Name VARCHAR(512)
    ,Value VARCHAR(800)
    )

INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')

我想以特定的方式将我的表数据转换为JSON值,如下所示:

预期输出:

 {
 "ThirdPartyInterfaceData": {
 "SMS":
 {
 "ThirdPartyInterfaceName": "PLIVO",
 "SYSTEM_SMSAuthID": "MAMDQ1ODNJN2JMMZMWZD",
 "SYSTEM_SMSAuthToken": "YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl",
 "SYSTEM_SMSFrom": "Venue Metro",
 "SYSTEM_SMSStatusMonitorURL": "http://www.google.com",
 "SYSTEM_SMSStatusMonitorURLMethod": "POST",
 "SYSTEM_SMSRestAPIVersion": "v1"
 }
 }
 }

我尝试使用FOR JSON AUTO,它提供了以下值:

当前输出:

[
    {
     "ThirdPartyInterfaceData":"SMS",
     "ThirdPartyInterfaceName":"PLIVO",
     "Name":"SYSTEM_SMSAuthID",
     "Value":"MAMDQ1ODNJN2JMMZMWZD"
    },
    {
     "ThirdPartyInterfaceData":"SMS",
     "ThirdPartyInterfaceName":"PLIVO",
     "Name":"SYSTEM_SMSAuthToken",
     "Value":"YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl"
    },..

    ..."
    }
]

但我的要求是上述格式,是否可能?任何人都可以帮我解决这个问题。

提前致谢。

1 个答案:

答案 0 :(得分:2)

我们可以使用动态SQL。我正在删除@Example表中的行,因此如果要使用我的解决方案而不删除主表中的行,则必须创建其他表并插入所有值。它应该适用于ThirdPartyInterfaceDataThirdPartyInterfaceName列中的多个不同值。 需要SQL Server 2016。

第一种方式(WHILE循环)

DECLARE @Example TABLE 
    (
    ThirdPartyInterfaceData VARCHAR(10)
    ,ThirdPartyInterfaceName VARCHAR(10)
    ,Name VARCHAR(512)
    ,Value VARCHAR(800)
    )

INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')


DECLARE @sql NVARCHAR(MAX)
DECLARE @value VARCHAR(800)
DECLARE @name VARCHAR(512)
DECLARE @ThirdPartyInterfaceData VARCHAR(10)
DECLARE @ThirdPartyInterfaceName VARCHAR(10)
DECLARE @new bit = 1 --We have to recognize when to add element ""ThirdPartyInterfaceName":"PLIVO","
DECLARE @start bit = 1 --This variable is only used in first iteration of WHILE
DECLARE @json NVARCHAR(MAX)

SET @sql = 'SELECT @json = (SELECT '

/*
    We are going to delete rows from table @Example, so we can use EXISTS in WHILE
*/
WHILE EXISTS(SELECT * FROM @Example)
BEGIN
    SELECT TOP 1
        @new = CASE WHEN @start = 0 THEN CASE 
                        WHEN @ThirdPartyInterfaceData IS NOT NULL AND @ThirdPartyInterfaceName IS NOT NULL 
                            AND (@ThirdPartyInterfaceData <> ThirdPartyInterfaceData OR @ThirdPartyInterfaceName <> ThirdPartyInterfaceName) 
                                THEN 1
                                ELSE 0
                        END
                ELSE 1 END,
        @ThirdPartyInterfaceData = ThirdPartyInterfaceData,
        @ThirdPartyInterfaceName = ThirdPartyInterfaceName,
        @name = name,
        @value = value

    FROM @Example
    ORDER BY ThirdPartyInterfaceData, ThirdPartyInterfaceName, Name

    SET @start = 0

    IF @new = 1
    BEGIN
        SET @sql = @sql + '''' +  @ThirdPartyInterfaceName + '''  AS ''ThirdPartyInterfaceData.' + @ThirdPartyInterfaceData + '.ThirdPartyInterfaceName'', '
    END

    /*
        Adding next element into JSON
    */
    SET @sql = @sql + '''' + @value + '''' + ' AS ''ThirdPartyInterfaceData.' + @ThirdPartyInterfaceData + '.' + @name + ''', '

    /*
        Deleting current row
    */
    DELETE FROM @Example WHERE @ThirdPartyInterfaceData = ThirdPartyInterfaceData AND
        @ThirdPartyInterfaceName = ThirdPartyInterfaceName AND
        @name = name AND
        @value = value

END

/*
    Deleting last, unnecessary comma and adding ' FOR JSON PATH'
*/
SET @sql = SUBSTRING(@sql,1,LEN(@sql) - 1) + ' FOR JSON PATH)'


/*
    Executing sql, setting JSON into variable
*/
EXECUTE sp_executesql @sql, N'@json nvarchar(max) OUTPUT', @json = @json OUTPUT

/*
    You can do whatever you want with this variable (insert into table etc.)
*/
SELECT @json

第二种方式(没有WHILE循环):

DECLARE @Example TABLE 
    (
    ThirdPartyInterfaceData VARCHAR(10)
    ,ThirdPartyInterfaceName VARCHAR(10)
    ,Name VARCHAR(512)
    ,Value VARCHAR(800)
    )

INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO @Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')

DECLARE @sql NVARCHAR(MAX) = 'SELECT @json = (SELECT '
DECLARE @json NVARCHAR(MAX)

SELECT
    @sql = @sql + JSON_Part
FROM (SELECT
            ThirdPartyInterfaceData,
            ROW_NUMBER() OVER (PARTITION BY ThirdPartyInterfaceData, ThirdPartyInterfaceName ORDER BY ThirdPartyInterfaceData, ThirdPartyInterfaceName, Name) AS Number,
            '''' + Value + ''' AS ''ThirdPartyInterfaceData.' + ThirdPartyInterfaceData + '.' + Name + ''',' AS JSON_Part
        FROM @Example
        UNION ALL
        SELECT DISTINCT
            ThirdPartyInterfaceData,
            0 AS Number,
            '''' + ThirdPartyInterfaceName + '''  AS ''ThirdPartyInterfaceData.' + ThirdPartyInterfaceData + '.ThirdPartyInterfaceName'', ' AS JSON_Part
        FROM @Example) a
ORDER BY ThirdPartyInterfaceData, Number

/*
    Deleting last, unnecessary comma and adding ' FOR JSON PATH)'
*/
SET @sql = SUBSTRING(@sql,1,LEN(@sql) - 1) + ' FOR JSON PATH)'


PRINT @sql


/*
    Executing sql
*/

EXECUTE sp_executesql @sql, N'@json nvarchar(max) OUTPUT', @json = @json OUTPUT

SELECT @json