mysql error 1064 хранимая процедура извлекает значение json в определенные столбцы таблицы - PullRequest
0 голосов
/ 08 мая 2018

Я хочу извлечь данные json переменной длины в существующую таблицу, но получаю следующую ошибку:

Код ошибки: 1064. У вас ошибка в синтаксисе SQL;проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса, который можно использовать рядом с параметром begin begin begin len;объявить я int;объявить майки варчар (60);объявите myvalue 'в строке 2

Кто-нибудь знает, как решить эту ошибку или как извлечь данные JSON переменной длины в существующую таблицу?

Это мой код:

drop procedure if exists wk; 
delimiter // 
create procedure wk(tb varchar(60), myjson json)   
begin
SET @LEN= (select JSON_LENGTH(myjson));
set @i=1;
set @mykey='initial';
set @myvalue='initial';
set @thekeys= (select JSON_keys(myjson));
set @mysql_1=concat("insert into ",tb," (");
set @mysql_2='(';
while @i < @len*2 do
select 3;
set @mykey = (select substring(substring_index(@thekeys,'"',@i+1),length(substring_index(@thekeys,'"',@i))+2));
set @myvalue = (select json_extract(myjson,concat('$.',@mykey)));
set @mysql_1= concat(@mysql, @mykey,","); 
set @mysql_2= concat(@mysql_2, @myvalue,",") ;
set @i =@i+2
end while;

set @mysql = concat(substring(@mysql_1,-1),") values ", substring(@mysql_2,-1)," );");

PREPARE stmt FROM @mysql;
EXECUTE stmt;

end
  //
delimiter ;

call wk('actor','{"actor_id": 1, "first_name": "NICK"}');

1 Ответ

0 голосов
/ 12 мая 2018

Непосредственной причиной ошибок, по-видимому, являются некоторые непечатаемые символы во второй и третьей строках вашей процедуры - непосредственно после delimiter //, а также после закрывающей скобки create procedure wk(tb varchar(60), myjson json).

Как только вы очистите эти символы, вы получите еще одну ошибку, которая скажет вам, что есть еще одна синтаксическая ошибка непосредственно перед end while (отсутствует точка с запятой после set @i =@i+2).

MySQL, как правило, очень хорошо сообщает вам, где именно он начинает сталкиваться с проблемами при попытке проанализировать ваши операторы, причем проблема непосредственно предшествует выделенному тексту. Здесь говорится, что проблема начинается с «начала», а проблема - непосредственно перед ней.

После устранения ошибок ваша процедура будет запущена и выведет «3» дважды. Однако @mysql будет иметь значение NULL, и никакие инструкции не будут подготовлены и выполнены.

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

mysql> SET @thekeys = JSON_KEYS('{"actor_id": 1, "first_name": "NICK"}');

mysql> SET @mykey = JSON_UNQUOTE(JSON_EXTRACT(@thekeys, '$[1]'));

mysql> SELECT @mykey;
+------------+
| @mykey     |
+------------+
| first_name |
+------------+

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

, например

DELIMITER //

DROP PROCEDURE IF EXISTS wk //
CREATE PROCEDURE wk(tbl VARCHAR(64), myjson JSON)
BEGIN
  DECLARE i INT DEFAULT 0;
  SET @keys = '';
  SET @vals = '';

  WHILE i < JSON_LENGTH(myjson) DO
    SET @mykey = JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(myjson), CONCAT('$[', i, ']')));
    SET @myval = JSON_UNQUOTE(JSON_EXTRACT(myjson, CONCAT('$.', @mykey)));

    SET @keys = CONCAT(@keys, IF(CHAR_LENGTH(@keys) > 0, ',', ''),
      CONCAT('`', @mykey, '`')); 
    SET @vals = CONCAT(@vals, IF(CHAR_LENGTH(@vals) > 0, ',', ''),
      CONCAT('''', @myval, ''''));
    SET i = i + 1;
  END WHILE;

  SET @sql = CONCAT('INSERT INTO `', tbl , '`(', @keys, ') VALUES (', @vals, ');');

  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;    

END //
DELIMITER ;

CALL wk('actor','{"actor_id": 1, "first_name": "NICK"}');
...