2017-03-29 10 views
1

ツリーをたどるように再帰的に呼び出すことができる関数(MS SQL Server 2016)が必要で、そのトラバーサルを単一のJson値として返すことができます。私は下に示すように、コードの作業塊を持っていますが、私は使用したclunky JSON_MODIFY以外の何かをしたいと思います。残念ながら、私はそれなしで動作させる方法を見つけることができません。 JSON_MODIFYを使ってコード行をコメントアウトし、次の行のコメントを外すと、私の意味がわかります。MS SQL Server:ColumnをJsonとして扱う

もっと良い解決策はありますか?

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\\\"}]\"}]"}] 

おかげで任意のアイデアのために進む。

答えて

0

2つのこと:

1)JSON_MODIFY()実際にはまさに私が欲しいものを生成しません。元のコードを使用して、JSON_MODIFYは、名前 'x'と値 ''を持つ要素を値に追加します。

2)JSON_MODIFY()をJSON_QUERY()(特にJSON_QUERY(dbo.NodeList(...)、 '$')に置き換える方がはっきりしていますが、このようにすると、余分な 'x'アーティファクトがなくなります。

SQLは明らかに、JSON_MODIFYから戻ってくるものは実際には(署名にもかかわらず)NVARCHARではないことを知っていますが、 SQLでNVARCHARがJSONであると考える方法。

関連する問題