2016-06-08 11 views
12

SQL 2016 verfügt über eine neue Funktion, die Daten auf SQL Server in JSON konvertiert. Ich habe Schwierigkeiten beim Array von Objekten in einem Array von Werten in Kombination dhSQL zu JSON - Array von Objekten zu Array von Werten in SQL 2016

Beispiel -

CREATE TABLE #temp (item_id VARCHAR(256)) 

INSERT INTO #temp VALUES ('1234'),('5678'),('7890') 

SELECT * FROM #temp 

--convert to JSON 

SELECT (SELECT item_id 
FROM #temp 
FOR JSON PATH,root('ids')) 

RESULT -

{ 
    "ids": [{ 
     "item_id": "1234" 
    }, 
    { 
     "item_id": "5678" 
    }, 
    { 
     "item_id": "7890" 
    }] 
} 

Aber ich das Ergebnis will wie -

"ids": [ 
     "1234", 
     "5678", 
     "7890" 
    ] 

Kann mir bitte jemand helfen?

+0

denke ich, dass vielleicht nur die Art und Weise sein, es funktioniert. [Sie werden vielleicht bemerken, dass FOR JSON ein Array von Schlüssel: Wert-Paaren zurückgibt, auch wenn wir vielleicht etwas Einfacheres wünschen, z. einfaches Array von Werten anstelle von Array von Objekten. In diesem Fall können wir eine einfache benutzerdefinierte T-SQL-Funktion schreiben, die Schlüssel aus dem Array entfernt und ein einfaches Array zurückgibt:] (https://blogs.msdn.microsoft.com/sqlservertorageengine/2015/10/09/returning-child- rows-formatiert-als-json-in-sql-server-queries /) –

Antwort

7

Danke! Die gefundene Lösung wird zunächst in XML konvertiert -

SELECT 
JSON_QUERY('[' + STUFF((SELECT ',' + '"' + item_id + '"' 
FROM #temp FOR XML PATH('')),1,1,'') + ']') ids 
FOR JSON PATH , WITHOUT_ARRAY_WRAPPER 
+0

Ich denke, aufgrund der Performance-Problem der FOR XML-Abfrage ist es keine gute Praxis –

5

Martin!

Ich glaube, dies ist eine noch einfachere Art und Weise tun:

SELECT '"ids": ' + 
    REPLACE( 
     REPLACE((SELECT item_id FROM #temp FOR JSON AUTO),'{"item_id":',''), 
     '"}','"') 
+1

Dies ist ein viel besserer Hack als jeder andere, den ich gesehen habe. Und leider hat dies den [Friedhof der Feature-Anfragen] (https://connect.microsoft.com/SQLServer/Feedback/Details/1383569) erreicht. – harpo

+0

Nun, ich wählte es um eins :-) –

0

Da Arrays von primitiven Werte gültig JSON sind, scheint es seltsam, dass eine Einrichtung für Arrays von primitiven Werte der Auswahl nicht in SQL gebaut Server-JSON-Funktionalität. (Wenn diese Funktionalität vorhanden ist, habe ich sie zumindest nach einiger Suche nicht entdecken können).

Der oben beschriebene Ansatz funktioniert wie beschrieben. Bei der Anwendung auf ein Feld in einer größeren Abfrage wird das Array von Primitiven jedoch in Anführungszeichen eingeschlossen.

Z. B. diese

DECLARE @BomTable TABLE (ChildNumber dbo.udt_ConMetPartNumber); 
INSERT INTO @BomTable (ChildNumber) VALUES (N'101026'), (N'101027'); 
SELECT N'"Children": ' + REPLACE(REPLACE((SELECT ChildNumber FROM @BomTable FOR JSON PATH), N'{"ChildNumber":', N''), '"}',''); 

Werken produziert:

"Children": ["101026,"101027] 

Aber nach dem Ansatz über diese:

SELECT 
    p.PartNumber, 
    p.Description, 
    REPLACE(REPLACE((SELECT 
         ChildNumber 
        FROM 
         Part.BillOfMaterials 
        WHERE 
         ParentNumber = p.PartNumber 
        ORDER BY 
         ChildNumber 
        FOR 
        JSON AUTO 
        ), N'{"ChildNumber":', N''), '"}', '"') AS [Children] 
FROM 
    Part.Parts AS p 
WHERE 
    p.PartNumber = N'104444' 
FOR 
    JSON PATH 

Produziert:

[ 
    { 
     "PartNumber": "104444", 
     "Description": "ASSY HUB   R-SER DRIV HP10 ABS", 
     "Children": "[\"101026\",\"101027\",\"102291\",\"103430\",\"103705\",\"104103\"]" 
    } 
] 

Wo die Kinder Array als Zeichenfolge umwickelt ist.

+0

Fügen Sie JSON_QUERY() um REPLACE. Dadurch wird redundantes Escaping deaktiviert – DiGi

1

Die meisten dieser Lösungen erstellen im Wesentlichen eine CSV-Datei, die den Array-Inhalt darstellt, und fügen diese CSV-Datei dann in das endgültige JSON-Format ein.Hier ist, was ich verwende, XML zu vermeiden:

DECLARE @tmp NVARCHAR(MAX) = '' 

SELECT @tmp = @tmp + '"' + [item_id] + '",' 
FROM #temp -- Defined and populated in the original question 

SELECT [ids] = JSON_QUERY((
    SELECT CASE 
     WHEN @tmp IS NULL THEN '[]' 
     ELSE '[' + SUBSTRING(@tmp, 0, LEN(@tmp)) + ']' 
     END 
    )) 
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER 
2
declare @temp table (item_id VARCHAR(256)) 

INSERT INTO @temp VALUES ('123"4'),('5678'),('7890') 

SELECT * FROM @temp 

--convert to JSON 

select 
    json_query(QUOTENAME(STRING_AGG('"' + STRING_ESCAPE(item_id, 'json') + '"', char(44)))) as [json] 
from @temp 
for json path 

Wenn wir verketten Zeichenfolge als JSON-Array wollen, dann:

1) Escape-String - STRING_ESCAPE

2) verketten Zeichenfolge mit Komma separator - STRING_AGG, comma ascii code ist 44

3) füge ihn in Klammern ein - QUOTENAME (ohne Parameter)

4) return string (mit Anordnung von Elementen) als json - JSON_QUERY

+0

STRING_AGG ist in SQL 2016 nicht verfügbar? – TaylorN