web-dev-qa-db-fra.com

SQL vers JSON - tableau d'objets vers tableau de valeurs dans SQL 2016

SQL 2016 a une nouvelle fonctionnalité qui convertit les données du serveur SQL en JSON. J'ai du mal à combiner un tableau d'objets dans un tableau de valeurs, c'est-à-dire

EXEMPLE -

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')) 

RÉSULTAT -

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

Mais je veux que le résultat soit -

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

Quelqu'un peut-il m'aider?

Merci! L'âme que nous avons trouvée convertit d'abord en XML -

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

Martin!

Je pense que c'est une façon encore plus simple de le faire:

    SELECT '"ids": ' + 
    REPLACE( 
      REPLACE( (SELECT item_id FROM #temp FOR JSON AUTO),'{"item_id":','' ),
      '"}','"' )
12
Magne Rekdal
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

Lorsque nous voulons concaténer des chaînes en tant que tableau json, alors:

1) chaîne d'échappement - STRING_ESCAPE

2) concaténer une chaîne avec un séparateur de virgules - STRING_AGG, le code ascii de la virgule est 44

3) ajouter la citation entre parenthèses - QUOTENAME (sans param)

4) retourne la chaîne (avec un tableau d'éléments) en json - JSON_QUERY

6
massther

Étant donné que les tableaux de valeurs primitives sont des JSON valides, il semble étrange qu'une fonction de sélection de tableaux de valeurs primitives ne soit pas intégrée dans la fonctionnalité JSON de SQL Server. (Si au contraire une telle fonctionnalité existe, je n'ai au moins pas pu la découvrir après pas mal de recherche).

L'approche décrite ci-dessus fonctionne comme décrit. Mais lorsqu'il est appliqué pour un champ dans une requête plus grande, le tableau de primitives est entouré de guillemets.

Par exemple, ce

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''), '"}','');

fonctionne en produisant:

"Children": ["101026,"101027]

Mais, en suivant l'approche ci-dessus, ceci:

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

Produit:

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

Où le tableau Enfants est encapsulé sous forme de chaîne.

4
CalvinDale

La plupart de ces solutions créent essentiellement un CSV qui représente le contenu du tableau, puis mettent ce CSV au format JSON final. Voici ce que j'utilise pour éviter XML:

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
1
Eric