SQL -SERVER: JSON_MODIFY для json столбца с соответствием поля "содержит" - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь выяснить, как изменить json, хранящийся в столбце моей таблицы (SQL SERVER).

Я хочу удалить свойство JSON, только если он соответствует заданной c строке.

Представьте, что в нашей таблице есть запись с этим JSON внутри столбца с именем "profile" (nvarchar (max)):

{ 
  name: "goofy",
  class_cod_x: "1345",
}

Затем еще одна запись представляет это JSON:

{ 
  name: "donald",
  class_cod_y: "1457",
}

Теперь мы хотим найти и обновить все JSON внутри наших записей, которое содержит свойство, которое начинается с"class_cod" ,

Я хочу удалить все свойства "class_cod .." из этого столбца.

Я могу представить запрос, подобный следующему:

UPDATE myTable SET profile = JSON_MODIFY( profile , "startsWith(class_cod)" , null)

Возможно ли это? В таком случае, какой правильный синтаксис? Заранее спасибо!

ОБНОВЛЕНИЕ Ожидаемый результат:

{ 
  name: "goofy",
}

и

{ 
  name: "donald",
}

Поле "class_cod" полностью удалено.

ОБНОВЛЕНИЕ 2

  • SQL ВЕРСИЯ СЕРВЕРА: Microsoft SQL Server 2016 (окончательная первоначальная версия) - 13.0.1601.5 (X64)

  • "name" и "class_cod .." не единственные возможные поля внутри столбца json. Это JSON основано на перечислении возможных конфигураций.

  • Возможно ли, что JSON содержит несколько полей "class_cod ..". (крайне редко, но возможно)

    {
      name: mario,
      class_cod_10: 22,
      class_cod_20: 31,
    }
    

Ответы [ 2 ]

1 голос
/ 27 апреля 2020

Я не думаю, что вы можете использовать подстановочные знаки для параметра path в JSON_MODIFY(), и если JSON в столбце profile имеет более одного ключа class_cod_*, вы можете попытаться сгенерировать и выполнить динамическое заявление c. Последний оператор включает в себя один оператор UPDATE для каждого отдельного ключа class_cod_* во всех JSON объектах из всех строк таблицы. Обратите внимание, что вам нужно использовать режим lax (по умолчанию), чтобы указать, что свойство, на которое ссылается путь, не должно существовать:

Таблица:

CREATE TABLE Data (profile nvarchar(max));
-- Rows with one `class_cod_*` key
INSERT INTO Data (profile) VALUES (N'{"name":"goofy","class_cod_x":"1345"}')
INSERT INTO Data (profile) VALUES (N'{"name":"donald","class_cod_y":"1457"}')
-- Row without `class_cod_*` key
INSERT INTO Data (profile) VALUES (N'{"name":"tom"}')
-- Row with one `class_cod_*` key and other keys
INSERT INTO Data (profile) VALUES (N'{"name":"goofy","class_cod_x":"1345","age":10}')
-- Row with two `class_cod_*` keys
INSERT INTO Data (profile) VALUES (N'{"name":"jerry", "class_cod_x":"1345", "class_cod_y":"1345"}')

Оператор:

DECLARE @stm nvarchar(max)
SELECT @stm = (
   SELECT CONCAT(
      CONCAT('UPDATE Data SET profile = JSON_MODIFY(profile, ''lax $."', t.[key], '"'', null)'),
      '; '
   )   
   FROM (
      SELECT DISTINCT j.[key]
      FROM Data d
      CROSS APPLY OPENJSON(d.profile) j
      WHERE j.[key] LIKE N'class_cod_%' 
   ) t
   FOR XML PATH('')
)
PRINT @stm
EXEC sp_executesql @stm

Результат:

profile
{"name":"goofy"}
{"name":"donald"}
{"name":"tom"}
{"name":"goofy","age":10}
{"name":"jerry"}
1 голос
/ 27 апреля 2020

Один из способов - создать динамические операторы обновления c и вручную запустить сгенерированный запрос на обновление. Примерно так.

SELECT 'UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,''$.' +x.[key]+ ''', null)'
FROM MYTABLE T
CROSS APPLY OPENJSON (profile, '$') x 
WHERE x.[key] LIKE '%class_cod%'

Этот запрос создаст список операторов обновления, как показано ниже.

UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,'$.class_cod_x', null)
UPDATE MYTABLE SET PROFILE=JSON_MODIFY(profile ,'$.class_cod_y', null)

Предположение: каждая запись JSON содержит ключ class_cod_* только один раз. Надеюсь, что есть только ограниченные строки, в которых вы можете вручную выполнить оператор обновления

Проверить демонстрацию здесь

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