@korolgri

Как обновить значения в колонке таблицы?

ExternalWorkItems - таблица, ExternalUrls - колонка в таблице
В ExternalUrls (jsonb) записаны значения формата [{"Url": "https://test/browse/CP-12", "Updated": "2020-12-15 15:57:45", "Comments": "", "JiraRemoteLinkId": 25628}]
Как массово обновить строки в этой колонке, заменив "https://test/browse/CP-12" на "https://example/browse/CP-12" ?
Отрезать первые N символы в json и заменить их на своё значение?
Пробовал:
update public."ExternalWorkItems" as ew
SET ew."ExternalUrls" = overlay (ew."ExternalUrls" placing 'http://test' from 1 for 30);

Ошибка:
SQL Error [42883]: ERROR: function pg_catalog.overlay(jsonb, unknown, integer, integer) does not exist
  Подсказка: No function matches the given name and argument types. You might need to add explicit type casts.
  • Вопрос задан
  • 366 просмотров
Решения вопроса 1
@galaxy
Есть разные варианты.
Можно работать с JSONB по-человечески:
функция jsonb_set() меняет значение по пути внутри JSON. В вашем случае как-то так:
jsonb_set(ExternalUrls, '{0,Url}', '"https://example/browse/CP-12"')
- заменит ключ Url в элементе с индексом 0 массива из ExternalUrls. Она возвращает новый JSONB объект, обновление колонок таблиц в SQL в любом случае делается через UPDATE:
UPDATE ExternalWorkItems
   SET ExternalUrls = jsonb_set(ExternalUrls, '{0,Url}', '"https://example/browse/CP-12"');

Есть некоторая проблемка в том, что jsonb_set меняет одно значение, т.е. нельзя использовать "мульти-путь" типа {*,Url}, чтобы поменять сразу все элементы массива ExternalUrls (если у вас их там больше одного).
Проблема решаемая через серию подзапросов с применением функций jsonb_array_elements() -> jsonb_set() -> jsonb_agg(), но уж какая-то монструозная выходит конструкция.

К тому же, если вам надо заменить часть строки (судя по всему, домен в ссылке), не трогая остальное, все становится еще хуже. Как-то так:
UPDATE ExternalWorkItems
   SET ExternalUrls = jsonb_set(
          ExternalUrls, '{0,Url}',
          to_jsonb(replace(ExternalUrls #>> '{0,Url}', 'test', 'example'))
   );

(опять поменяет только первый элемент массива ExternalUrls)

Посему, предлагается небольшой костыль в виде конвертации JSONB в текст и простой замене (с некоторым риском заменить не то, что нужно... но если вы уверены в структуре, то это не проблема):
UPDATE ExternalWorkItems SET ExternalUrls = replace(ExternalUrls::text, 'https://test', 'https://example')::jsonb;
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы