T SQL - Извлечение JSON значений для неизвестного / динамического c ключа в подобъекте (не массиве) - PullRequest
0 голосов
/ 30 января 2020

Я использую DataTables, DataTables Editor, JavaScript и MS SQL 2016.

Я хочу проанализировать эту строку в SQL Server:

{
    "action":"edit",
    "data": { 
                "2019-08-03":{ 
                                "Description":"sdfsafasdfasdf",
                                "FirstFrozenStep":"333"
                             }
            }
}

Я не знаю, как получить доступ к ключу "2019-08-03". Это представляет первичный ключ или DT_RowId в редакторе DataTables. Это динамически c ... Это может измениться.

Исторически, я только что манипулировал данными в JavaScript в объект FLAT, который СЛЕДУЕТ анализировать на SQL Server:

{
     "action":"edit",
     "DT_RowId":"2019-08-03",
     "Description":"sdfsafasdfasdf",
     "FirstFrozenStep":"333"
}

ОДНАКО, я хотел бы знать, как использовать json_query, json_value и openjson(), чтобы перейти к ключу «dynamici c», упомянутому выше, и затем получить доступ к его значениям.

Вот все мои неудачные попытки:

declare
    @jsonRequest nvarchar(max) = '{"action":"edit","data":{"2019-08-03":{"Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}}}'
    ,@json2 nvarchar(max) = '{"2019-08-03":{"Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}}'
    ,@jsonEASY nvarchar(max) = '{"action":"edit","DT_RowId":"2019-08-03","Description":"sdfsafasdfasdf","FirstFrozenStep":"333"}'


    select
        json_value(@jsonRequest, '$.action') as [action]
        --,json_value(@jsonRequest, '$.data.[0]') as [action]
        --,json_query(@jsonRequest, '$.data[0]')
        --,json_query(@jsonRequest, '$.data.[0]')
        --,json_query(@jsonRequest, '$.data[0].Description')
        --,json_query(@jsonRequest, '$.data.Description')
        --,json_query(@jsonRequest, '$.data.[0].Description')


select
    [Key]
    ,Value
    ,Type
    --,json_query(value, '$')
from
    openjson(@jsonRequest)



SELECT x.[Key], x.[Value]
FROM OPENJSON(@jsonRequest, '$') AS x;

select
    x.[Key]
    ,x.[Value]
    --,json_query(x.value, '$')
    --,(select * from openjson(x.value))
FROM OPENJSON(@jsonRequest, '$') AS x;

SELECT x.[Key], x.[Value]
FROM OPENJSON(@json2, '$') AS x;


    select
        json_value(@jsonEASY, '$.action') as [action]
        ,json_value(@jsonEASY, '$.DT_RowId') as [DT_RowId]
        ,json_value(@jsonEASY, '$.Description') as [Description]

Ответы [ 2 ]

1 голос
/ 31 января 2020

Наиболее явный и безопасный для типов подход может быть следующим:

Я определяю ваш JSON с помощью двух dynamici c ключей

DECLARE @json NVARCHAR(MAX)=
N'{
    "action":"edit",
    "data": { 
                "2019-08-03":{ 
                                "Description":"sdfsafasdfasdf",
                                "FirstFrozenStep":"333"
                             },
                "2019-08-04":{ 
                                "Description":"blah4",
                                "FirstFrozenStep":"444"
                             }
            }
}';

- - запрос

SELECT A.[action]
      ,B.[key]
      ,C.*
FROM OPENJSON(@json) WITH([action]  NVARCHAR(100)
                         ,[data]    NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.[data]) B 
OUTER APPLY OPENJSON(B.[value]) WITH([Description] NVARCHAR(100)
                                     ,FirstFrozenStep INT) C;

Результат

action  key         Description     FirstFrozenStep
edit    2019-08-03  sdfsafasdfasdf  333
edit    2019-08-04  blah4           444

Идея вкратце:

  • Первый OPENJSON() вернет два первый Ключи уровня под псевдонимом A. Элемент data возвращается AS JSON, что позволяет продолжить это позже.
  • Второй OPENJSON() получает A.[data] в качестве ввода и необходим для получения руки на key, который ваша дата.
  • Третий OPENJSON() теперь получает B.[value] в качестве входных данных.

Предложение WITH позволяет читать внутренние элементы, неявно поворачиваемые и набираемые.

В общем : В обобщенных c контейнерах данных не имеет смысла использовать описательные части в качестве содержимого . Это возможно и может показаться умным, но было бы намного лучше поместить вашу дату как контент в ключе date.

1 голос
/ 30 января 2020

Вы можете использовать OUTER APPLY, чтобы перейти на следующий уровень в JSON:

SELECT L1.[key], L2.[key], L2.[value]
FROM openjson(@json,'$.data') AS L1
OUTER APPLY openjson(L1.[value]) AS L2

Будет возвращено:

key         key             value  
2019-08-03  Description     sdfsafasdfasdf  
2019-08-03  FirstFrozenStep 333
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...