Как передать строку в формате JSON из Excel VBA в качестве аргумента в хранимую процедуру MySQL

У меня есть следующая хранимая процедура в MySQL, которая читает массив объектов JSON и вставляет объекты в столбец JSON временной таблицы:

DELIMITER $$
DROP PROCEDURE IF EXISTS proc_json $$
CREATE OR REPLACE PROCEDURE myProcedure(IN myjson TEXT)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE qryStmt TEXT;
DROP TEMPORARY TABLE IF EXISTS tempTable;
CREATE TEMPORARY TABLE tempTable(update_key int NOT NULL AUTO_INCREMENT, update_data JSON, PRIMARY KEY(update_key));
WHILE i < JSON_LENGTH(myjson) DO
    SET qryStmt = CONCAT("INSERT INTO tempTable VALUES(DEFAULT, (JSON_EXTRACT('", myjson,"','$[",i,"]')))");
    PREPARE stmt FROM qryStmt;
    EXECUTE stmt;
    SET i = i+1;
END WHILE;
END $$
DELIMITER ;

Хранимая процедура отлично работает, когда я вызываю процедуру в MySQL >CALL myProcedure('[{"firstname": "Tom", "lastname": "Cruise", "occupation": "Actor"}, {"firstname": "Al", "lastname": "Pacino", "occupation": "Actor"}]');, она считывает строку как отдельные объекты JSON и вставляет их как записи в таблицу.

У меня также есть следующий Sub в Excel VBA, который намеревается вызвать хранимую процедуру, передав массив объектов в формате JSON хранимой процедуре:

Sub proc_jason()

On Error GoTo ErrorHandler

Dim strConnection, jsonString As String

Set objConnection = New ADODB.Connection
Set objRecordset = New ADODB.Recordset

jsonString = "[{""firstname"": ""Tom"", ""lastname"": ""Cruise"", ""occupation"": ""Actor""}, " _
             & "{""firstname"": ""Alfredo"", ""lastname"": ""Pacino"", ""occupation"": ""Actor""}]"

strConnection = "Driver = {MySQL ODBC 8.0 ANSI Driver}; Server=[IP]; Database=[Db]; user=[usr]; PWD=[pwd]"
objConnection.Open strConnection
         
With objRecordset
    .CursorLocation = adUseClient
    .CursorType = adOpenStatic
    .Open "CALL myProcedure('" & jsonString & "');", objConnection, adOpenForwardOnly, adLockReadOnly, adCmdStoredProc
End With

objRecordset.Close
Set objRecordset = Nothing
objConnection.Close
Set objConnection = Nothing

Exit Sub

ErrorHandler:
    MsgBox Err.Description

End Sub

Sub возвращает следующую ошибку:

Я видел сообщения, вызывающие хранимую процедуру MySQL с использованием объекта Command:

With objCommand
    .ActiveConnection = objConnection
    .CommandType = adCmdStoredProc
    .CommandText = "CALL myProcedure('" & jsonString & "');"
    .Execute
End With

Но я все еще получаю то же сообщение об ошибке. Любая помощь приветствуется.

Сомневаюсь, что [[{ правильно. Пожалуйста, проверьте, какие и сколько скобок требуется.

Stringeater 31.03.2023 23:46

Спасибо, исправил, сообщение об ошибке осталось прежним. Согласно синтаксису в MySQL это должна быть одна скобка. >CALL myProcedure('[{json-array}]');

M Garcia 31.03.2023 23:52

Возможно, попробуйте использовать параметризованный вызов - например. stackoverflow.com/a/40831427/478884

Tim Williams 01.04.2023 00:55

Добавьте несколько vbCrLf в свой json. Возможно, это даст вам лучшее сообщение об ошибке.

Sam 01.04.2023 11:18

Тим, я изменил Sub с помощью параметризованного вызова. Один вопрос, я так понимаю третий параметр инструкции objCommand.CreateParameter это длина вводимой строки, верно? Я ввожу случайное число 500, как мне определить этот параметр, если я не знаю длину строки? Когда я запускаю Sub, нет сообщения об ошибке, но хранимая процедура не запускается, таблица не создается, как ожидалось.

M Garcia 01.04.2023 15:12

Сэм, добавил vbCrLF, сообщение об ошибке Error: (-2147217900) [MySQL][ODBC 8.0(a) Driver][mysqld-5.5.5-10.3.38-MariaDB]You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CALL myProcedure('[{"firstname": "Tom", "lastname": "Cruise", "occupation": "...' at line 1 16

M Garcia 01.04.2023 16:31
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
6
113
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Установите длину параметра на длину строки json.

Option Explicit

Sub demo()

    Dim con As ADODB.Connection
    Set con = New ADODB.Connection
    con.Open "mysqlu" ' dsn
    
    Const json = "a json string"
    
    With New ADODB.Command
        .ActiveConnection = con
        .CommandType = adCmdStoredProc
        .CommandText = "myProcedure"
        .Parameters.Append .CreateParameter("P1", adLongVarChar, adParamInput, Len(json), json)
        MsgBox .Execute.GetString
    End With
    con.Close
  
End Sub

CREATE PROCEDURE `myProcedure`(IN myjson TEXT)
BEGIN
    select myjson as result;
END

Благодаря вкладу Сэма и CPD1802 окончательный сработавший сабвуфер выглядит следующим образом:

Sub demo()

On Error GoTo errHandler

    Dim conn As ADODB.Connection
    Set conn = New ADODB.Connection
    conn.Open "Driver = {MySQL ODBC 8.0 ANSI Driver}; Server=ip; Database=db; user=usr; password=psw"
    
    Const json = "[{""firstname"": ""Tom"", ""lastname"": ""Cruise"", ""occupation"": ""Actor""}, " _
             & "{""firstname"": ""Alfredo"", ""lastname"": ""Pacino"", ""occupation"": ""Actor""}, " _
             & "{""firstname"": ""Winston"", ""lastname"": ""Churchill"", ""occupation"": ""Politician""}]"
    
    With New ADODB.Command
        .ActiveConnection = conn
        .CommandType = adCmdStoredProc
        .CommandText = "myProcedure"
        .Parameters.Append .CreateParameter("myjson", adLongVarChar, adParamInput, Len(json), json)
        MsgBox .Execute.GetString
    End With
    conn.Close
    
    Exit Sub

errHandler:
    MsgBox Err.Description
    
End Sub

Нет сообщения об ошибке, но хранимая процедура не вставила записи в таблицу. Я пропустил ВРЕМЕННО в строках хранимой процедуры:

DROP TABLE IF EXISTS tempTable;
CREATE TABLE tempTable(update_key int NOT NULL AUTO_INCREMENT, update_data JSON, PRIMARY KEY(update_key));

И теперь это работает, по какой-то причине использование TEMPORARY TABLE при вызове хранимой процедуры из Excel VBA не работает.

ВРЕМЕННАЯ таблица видна только для текущего сеанса и автоматически удаляется при закрытии сеанса.

CDP1802 01.04.2023 21:46

Я запустил Sub во время входа в сеанс MySQL, временная таблица существовала, но была пустой, ни таблица не была удалена после запуска Sub, ни записи не были вставлены. Я не думаю, что подсистема выполняет хранимую процедуру с ВРЕМЕННЫМИ ТАБЛИЦАМИ.

M Garcia 01.04.2023 23:15

Временная таблица в вашем сеансе отличается от таблицы в сеансе adodb, даже если они могут иметь одно и то же имя. У Microsoft sql есть глобальные временные таблицы, доступные между сеансами, но я не думаю, что у mysql есть.

CDP1802 01.04.2023 23:33

Другие вопросы по теме

Похожие вопросы

1064, «У вас есть ошибка в синтаксисе SQL; проверьте в руководстве, которое соответствует вашей базе данных MariaDB, правильный синтаксис для использования рядом с 'str.' в строке 1"
Запрос Mysql, где отношение многие ко многим содержит все значение массива по крайней мере
Контекст выполнения пакета Spring закодирован
Выберите данные из предыдущего, которые имеют тот же идентификатор, и я использую 2 идентификатора, первый идентификатор для параметра и второй идентификатор для остановки расчета
Я не понимаю, почему я не могу подключиться к mysql с помощью многоконтейнерного приложения docker compose golang mariadb/mysql
Хотите получить данные из базы данных и отобразить их в html-файле
Как получить имена столбцов двух таблиц одновременно
Как открыть и транспонировать список в MySQL
Как загрузить данные в несколько таблиц SQL
Почему столбец JSON не может быть уникальным ключом?