SELECT динамический JSON хранится в SQL как часть запроса выбора - PullRequest
0 голосов
/ 15 марта 2019

Я знаю, что подобные вопросы задавались несколько раз, однако мой сценарий выглядит несколько иначе.

Моя таблица базы данных выглядит следующим образом:

App ID    |    ID     |     JSONData      |     URL      |     CreatedOn
----------+-----------+-------------------+--------------+-----------------
5b5cd8    |    1      | {"F":"B", "S":"D"}| http://local | Mar 19 2018 13:04
5b5cd8    |    2      | {"F":"C", "S":"K"}| http://remote| Mar 29 2018 09:34
6b9df0    |    3      | {"T":"N", "D":"S"}| http://site  | Apr 04 2018 16:12

App ID столбец может иметь различные значения, однако структура JSONData (* должна быть) одинакова для того же App ID.

Можно ли как-нибудь разделить данные JSONData и получить такой результат?

App ID    |    ID     |  F  |  S  |     URL      |     CreatedOn
----------+-----------+-----+-----+--------------+-------------------------
5b5cd8    |    1      |  B  |  D  | http://local | Mar 19 2018 13:04
5b5cd8    |    2      |  C  |  K  | http://remote| Mar 29 2018 09:34

Для следующего App ID это так

App ID    |    ID     |  T  |  D  |     URL      |     CreatedOn
----------+-----------+-----+-----+--------------+-------------------------
6b9df0    |    3      |  N  |  S  | http://site  | Apr 04 2018 16:12

Примечание: Данные в поле JSONData по большей части будут иметь глубину на один уровень, т.е. все данные будут строковыми и никаких дополнительных объектов.

Решение, которое я нашел в большинстве случаеввремя, например this , либо использовало статические имена ключей JSON для разделения, либо создавало временную таблицу, которая может вызвать проблемы с производительностью.

1 Ответ

0 голосов
/ 15 марта 2019

Вам уже говорили, что имена столбцов набора результатов должны быть известны заранее.

Единственный обходной путь - динамический SQL (создание оператора в виде строки и EXEC() для получения его результата). Но у этого есть некоторые существенные недостатки (и некоторые преимущества) ...

Вы можете пойти с этим (требуется SQL-Server 2016 +):

A макет-стол

DECLARE @tbl TABLE(AppID VARCHAR(100),ID INT,JSONData NVARCHAR(MAX));
INSERT INTO @tbl VALUES
 ('5b5cd8',1,N'{"F":"B", "S":"D"}')
,('5b5cd8',2,N'{"F":"C", "S":"K"}')
,('6b9df0',3,N'{"T":"N", "D":"S"}');

- этот запрос извлекает значения, используя JSON_VALUE
- Вам нужно создать одно утверждение для каждого возможного списка столбцов
- Примените WHERE для фильтрации по соответствующим строкам

SELECT t.AppID
      ,t.ID
      ,JSON_VALUE(t.JSONData,'$.F') AS F
      ,JSON_VALUE(t.JSONData,'$.S') AS S
FROM @tbl t
WHERE t.AppID='5b5cd8'

- Вы можете включить все возможные столбцы
- Это работает без фильтра, но вернет много NULL

SELECT t.AppID
      ,t.ID
      ,JSON_VALUE(t.JSONData,'$.F') AS F
      ,JSON_VALUE(t.JSONData,'$.S') AS S
      ,JSON_VALUE(t.JSONData,'$.T') AS T
      ,JSON_VALUE(t.JSONData,'$.D') AS D
FROM @tbl t

- немного чище / лучше читать было OPENJSON() в связи с WITH -клаузой

SELECT t.AppID
      ,t.ID
      ,JsonColumns.*
FROM @tbl t
CROSS APPLY OPENJSON(t.JSONData) WITH(F CHAR(1)
                                     ,S CHAR(1)
                                     ,T CHAR(1)
                                     ,D CHAR(1)) JsonColumns 

Мое предложение: создайте последний как VIEW или (возможно, лучше) iTVF и используйте специальные операторы против этого, по одному на каждый тип структуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...