MS SQL Server:将列视为Json

时间:2017-03-29 15:45:40

标签: sql-server json

我想要一个函数(MS SQL Server 2016),它可以递归地调用自身来遍历树并将该遍历作为单个Json值返回。我有一大堆代码,如下所示,但我想做的事情不仅仅是我用过的笨重的JSON_MODIFY。不幸的是,如果没有它,我无法找到让它工作的方法。如果你用JSON_MODIFY注释掉代码行并取消注释下一行,你就会明白我的意思。

有更好的解决方案吗?

DROP TABLE dbo.Node;
GO

DROP FUNCTION dbo.NodeList;
GO

CREATE TABLE dbo.Node (
    NodeId INT NOT NULL ,
    ParentNodeId INT NULL ,
    NodeName NVARCHAR(MAX)
);
GO

INSERT  dbo.Node(NodeId, ParentNodeId, NodeName)
VALUES  (1, NULL, 'A'), (2, 1, 'B'), (3, 1, 'C'), (4, 3, 'D'), (5, 3, 'E');
GO

CREATE FUNCTION dbo.NodeList(@ParentNodeId INT) RETURNS NVARCHAR(MAX)
AS BEGIN
    DECLARE @JsonOut NVARCHAR(MAX) = (
        SELECT  n.NodeId ,
                n.NodeName ,
                JSON_MODIFY(dbo.NodeList(n.NodeId), '$.x', '') AS Children
                -- dbo.NodeList(n.NodeId) AS Children
        FROM    dbo.Node n
        WHERE   ISNULL(n.ParentNodeId, -1) = ISNULL(@ParentNodeId, -1)
        FOR JSON AUTO
        ) ;
    RETURN @JsonOut;
END;
GO

PRINT dbo.NodeList(NULL);
GO

JSON_MODIFY的输出正是我想要的......

[{"NodeId":1,"NodeName":"A","Children":[{"NodeId":2,"NodeName":"B"},
{"NodeId":3,"NodeName":"C","Children":[{"NodeId":4,"NodeName":"D"},
{"NodeId":5,"NodeName":"E"}]}]}]

......但没有它,一切都会出错...

[{"NodeId":1,"NodeName":"A","Children":"[{\"NodeId\":2,\"NodeName\":\"B\"},
{\"NodeId\":3,\"NodeName\":\"C\",\"Children\":\"
[{\\\"NodeId\\\":4,\\\"NodeName\\\":\\\"D\\\"},
{\\\"NodeId\\\":5,\\\"NodeName\\\":\\\"E\\\"}]\"}]"}]

提前感谢任何想法。

1 个答案:

答案 0 :(得分:0)

两件事:

1)JSON_MODIFY()实际上并不能完全生成我想要的内容。使用原始代码,JSON_MODIFY将一个名为“x”的元素和值“”添加到值中。

2)虽然不是一个完美的答案,但用JSON_QUERY()(特别是JSON_QUERY(dbo.NodeList(...),'$')替换JSON_MODIFY()更清晰。它不仅更有意义,这样就可以摆脱额外的'x'神器。

SQL显然知道从JSON_MODIFY返回的内容并不仅仅是一个NVARCHAR(尽管它的签名),但是我找不到任何其他方法让SQL认为NVARCHAR是JSON。