Как ВСТАВИТЬ объекты JSON в массив в MySQL?

#mysql #json #triggers #normalization #transformation

#mysql #json #триггеры #нормализация #преобразование

Вопрос:

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

Ниже приведены структура и пример нашей старой таблицы:

 SELECT * FROM TabHmIds;

ID  EntitlementID   TabId   HmId
1   101             201     301
2   102             202     302
  

Требуемая структура и образец нашей новой таблицы должны выглядеть следующим образом:

 SELECT * FROM tab_integration;
id  tab_id  integration_id  metadata
1   201     1               { "paid_id": {"entitlement_id": 101, "id": 301} }
2   202     1               { "paid_id": {"entitlement_id": 202, "id": 302} }
  

Следующее — это то, что я до сих пор делал в своем триггере INSERT:

 CREATE TRIGGER tab_integration_after_insert AFTER INSERT ON `TabHmIds` 
FOR EACH ROW 
BEGIN 

DECLARE var_metadata JSON;
DECLARE var_new_metadata JSON;
DECLARE var_hm_metadata JSON;
DECLARE var_integration_id INT(11);

SELECT
  metadata,
  integration_id INTO var_metadata,
  var_integration_id
FROM
  `go`.`tab_integration` gti
WHERE
  gti.`tab_id` = NEW.`TabId`;

SET var_hm_metadata = JSON_OBJECT('entitlement_id', NEW.`EntitlementId`, 'id', NEW.`HmId`);

IF var_integration_id = 1 THEN 
    
    IF var_metadata IS NULL THEN
        SET var_new_metadata = JSON_OBJECT('paid_id', var_hm_metadata);
        
    ELSE
        SET @paid_id = JSON_UNQUOTE(JSON_EXTRACT(var_metadata, '$.paid_id'));        
        SET var_new_metadata = JSON_ARRAY_APPEND(var_metadata, '$.paid_id', var_hm_metadata);

    END IF;
    
END IF;

UPDATE `tab_integration` gti SET `metadata` = var_new_metadata WHERE `tab_id` = NEW.`TabId`;

END
  

Однако, что я получаю, это:

 SELECT * FROM tab_integration;

id  tab_id  integration_id  metadata
1   201     1               { "paid_id": "{"entitlement_id": 101, "id": 301}" }
2   202     1               { "paid_id": "{"entitlement_id": 202, "id": 302}" }
  

Из приведенной выше таблицы объект JSON преобразуется в СТРОКУ. Я знаю, что JSON_OBJECT преобразует переданное значение в строку. ИТАК, я использовал JSON_UNQUOTE(JSON_EXTRACT(…)) для преобразования значения пути paid_id в JSON, но оно не анализируется в JSON. Я также попробовал JSON_MERGE_PRESERVE, чтобы поместить объект JSON по пути paid_id, но в итоге я получаю:

 {“paid_id”: [], “entitlement_id”: 101, “id”: 301 }
  

Я также попытался поместить массив JSON во временную таблицу с помощью JSON_TABLE и изменить значения во временной и преобразовать эту временную таблицу в JSON с помощью JSONARRAYAGG. Но Workbench продолжает говорить, что у меня ошибка в синтаксисе, хотя я напрямую скопировал примеры из Интернета.

Я также пытался преобразовать правильно сформированную строку в JSON, но Workbench также выдает синтаксическую ошибку. Я потратил неделю на разрешение этой структуры данных в MySQL.

Создание сценариев для баз данных не является моей сильной стороной, и я новичок в функциях JSON в MySQL. Заранее спасибо тем, кто ответит.

Если в случае необходимости, мой MySQL Workbench имеет версию 10.4.13-MariaDB. Но скрипт должен работать в MySQL 5.7.

Комментарии:

1. Не используйте массивы. Я нашел очень мало случаев, когда они имеют смысл. Большую часть времени они просто усложняют ситуацию.

2. Привет @TheImpaler. Итак, я должен просто рекомендовать реструктурировать нормализованную таблицу? Означает ли это, что моя проблема вообще не выполнима? Заранее спасибо.

Ответ №1:

Я нашел ответ на свою проблему.

Перед вставкой новых данных JSON я проанализировал их в CHAR и заменил символы, превратив их в строку. Я сделал следующее, и это сработало!

 # After performing the needed JSON manipulations, cleanse the JSON string to JSON.

SET var_new_metadata = CAST(var_new_metadata AS CHAR);

SELECT REPLACE(REPLACE(REPLACE(var_new_metadata, '\', ''), '"{', '{'), '}"', '}') INTO var_new_metadata;
  

После очистки данных вызов UPDATE все еще работал и попытался выполнить некоторые манипуляции с JSON после и, да, все еще работает!