У меня есть следующая хранимая процедура в 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
Но я все еще получаю то же сообщение об ошибке. Любая помощь приветствуется.
Спасибо, исправил, сообщение об ошибке осталось прежним. Согласно синтаксису в MySQL это должна быть одна скобка. >CALL myProcedure('[{json-array}]');
Возможно, попробуйте использовать параметризованный вызов - например. stackoverflow.com/a/40831427/478884
Добавьте несколько vbCrLf
в свой json. Возможно, это даст вам лучшее сообщение об ошибке.
Тим, я изменил Sub с помощью параметризованного вызова. Один вопрос, я так понимаю третий параметр инструкции objCommand.CreateParameter это длина вводимой строки, верно? Я ввожу случайное число 500, как мне определить этот параметр, если я не знаю длину строки? Когда я запускаю Sub, нет сообщения об ошибке, но хранимая процедура не запускается, таблица не создается, как ожидалось.
Сэм, добавил 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
Установите длину параметра на длину строки 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 не работает.
ВРЕМЕННАЯ таблица видна только для текущего сеанса и автоматически удаляется при закрытии сеанса.
Я запустил Sub во время входа в сеанс MySQL, временная таблица существовала, но была пустой, ни таблица не была удалена после запуска Sub, ни записи не были вставлены. Я не думаю, что подсистема выполняет хранимую процедуру с ВРЕМЕННЫМИ ТАБЛИЦАМИ.
Временная таблица в вашем сеансе отличается от таблицы в сеансе adodb, даже если они могут иметь одно и то же имя. У Microsoft sql есть глобальные временные таблицы, доступные между сеансами, но я не думаю, что у mysql есть.
Сомневаюсь, что
[[{
правильно. Пожалуйста, проверьте, какие и сколько скобок требуется.