Пожалуйста, помогите мне с моим вопросом: Ниже я упомянул хранимую процедуру в Oracle, и мне нужно преобразовать ее в MySQL.
CREATE OR REPLACE procedure EAMP.EXEC_DDL (SQLSTMT VARCHAR2) AUTHID DEFINER
is
BEGIN
EXECUTE IMMEDIATE SQLSTMT
END EXEC_DDL;
/
Вот что я создал в MySQL (версия 5.7):
DROP PROCEDURE IF EXISTS EXEC_DDL;
CREATE DEFINER=`ampd_own`@`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set @sql = SQLSTMT;
PREPARE STMT FROM @sql;
EXECUTE STMT;
deallocate prepare STMT;
END;
но это дает мне указанную ниже ошибку:
20:08:43 START Executing, Database Connection: EAMP DEV MYSQL Database Type: MYSQL Catalog: ampd01 Schema: null
20:08:47 INFO Physical database connection acquired for: EAMP DEV MYSQL
20:08:47 WARNING [DROP - 0 rows, 0.994 secs] OK. No rows were affected
SQLWarning:
Code: 1305 SQL State: 42000 --- PROCEDURE ampd01.EXEC_DDL does not exist
DROP PROCEDURE IF EXISTS EXEC_DDL;
20:08:48 FAILED [CREATE - 0 rows, 1.245 secs] [Code: 1064, SQL State:
42000] You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near ''
at line 4
CREATE DEFINER=`ampd_own`@`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set @sql = SQLSTMT;
20:08:49 FAILED [PREPARE - 0 rows, 1.243 secs] [Code: 1064, SQL State:
42000] You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near
'NULL' at line 1
PREPARE STMT FROM @sql;
20:08:51 FAILED [EXECUTE - 0 rows, 1.253 secs] [Code: 1243, SQL State:
HY000] Unknown prepared statement handler (STMT) given to EXECUTE
EXECUTE STMT;
20:08:52 FAILED [DEALLOCATE - 0 rows, 1.255 secs] [Code: 1243, SQL State:
HY000] Unknown prepared statement handler (STMT) given to DEALLOCATE
PREPARE
deallocate prepare STMT;
20:08:53 FAILED [END - 0 rows, 1.253 secs] [Code: 1064, SQL State: 42000]
You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'END' at line 1
END;
20:08:55 END Execution 6 statement(s) executed, 0 row(s) affected,
exec/fetch time: 7.243/0.000 secs [1 successful, 1 Warnings, 5 errors]*/






С точкой с запятой в теле процедуры нам нужно изменить разделитель операторов для сеанса.
Например:
DELIMITER $$
CREATE PROCEDURE foo()
BEGIN
SELECT NOW();
END$$
DELIMITER ;
При этом точка с запятой, которая появляется в хранимой процедуре, не завершает оператор CREATE. И мы можем изменить разделитель операторов обратно на точку с запятой, когда мы закончим.
РЕДАКТИРОВАТЬ
Вот анализ полученных результатов:
Это утверждение
DROP PROCEDURE IF EXISTS EXEC_DDL;
завершено успешно, появляется предупреждение "процедура не существует"
Следующий выполненный оператор был таким:
CREATE DEFINER=`ampd_own`@`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set @sql = SQLSTMT;
MySQL вернул синтаксическую ошибку; что является ожидаемым поведением, потому что это недопустимый оператор SQL. Выполняется следующий оператор:
PREPARE STMT FROM @sql;
вернул ошибку, потому что @sql оценивается как NULL. Выполняется следующий оператор
EXECUTE STMT;
не удалось, потому что STMT не является допустимым дескриптором оператора. (Потому что ПОДГОТОВКА потерпела неудачу.)
Мы не хотим выполнять SET и PREPARE как отдельные операторы, мы хотим, чтобы они были частью оператора CREATE PROCEDURE.
Проблема в том, что символ точки с запятой является терминатором оператора; нам нужно изменить терминатор оператора, чтобы он был чем-то другим, на некоторую строку, которая не появляется в теле CREATE PROCEDURE.
СЛЕДОВАТЬ ЗА
Ссылка: https://dev.mysql.com/doc/refman/5.7/en/stored-programs-defining.html
Вот демонстрация использования клиента командной строки MySQL
# mysql --defaults-extra-file=/opt/mysql/scripts/config.cnf --database test
mysql> DELIMITER $$
mysql> DROP PROCEDURE IF EXISTS foo $$
Query OK, 0 rows affected (0.06 sec)
mysql> DROP PROCEDURE IF EXISTS foo $$
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE PROCEDURE foo()
-> BEGIN
-> SELECT NOW();
-> END$$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> CALL foo();
+---------------------+
| NOW() |
+---------------------+
| 2018-06-13 13:33:33 |
+---------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Я также попытался определить терминатор оператора, и код выглядит следующим образом: DROP PROCEDURE IF EXISTS EXEC_DDL; DELIMITER $$ CREATE DEFINER = ampd_own @ % PROCEDURE ampd01.EXEC_DDL (в SQLSTMT VARCHAR (4000)) BEGIN set @sql = SQLSTMT; ПОДГОТОВЬТЕ STMT ОТ @sql; ВЫПОЛНИТЬ STMT; освободить подготовить STMT; END $$ DELIMITER;
но это дало мне указанную ниже ошибку msg: 12:20:44 FAILED [DELIMITER - 0 rows, 1.264 secs] [Code: 1064, SQL State: 42000] У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис рядом с 'DELIMITER $$ CREATE DEFINER = ampd_own @ % PROCEDURE ampd01.EXEC_DDL (в SQLS' в строке 1 DELIMITER $$ CREATE DEFINER = ampd_own @ % PROCEDURE ampd01. EXEC_DDL (в SQLSTMT VARCHAR (4000)) НАЧАТЬ установить @sql = SQLSTMT;
12:20:46 СБОЙ [ПОДГОТОВКА - 0 строк, 1,263 секунды] [Код: 1064, состояние SQL: 42000] У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, чтобы найти правильный синтаксис для использования рядом с 'NULL' в строке 1 PREPARE STMT FROM @sql; 12:20:47 FAILED [ВЫПОЛНИТЬ - 0 строк, 1,248 секунды] [Код: 1243, состояние SQL: HY000] Неизвестный обработчик подготовленных операторов (STMT) передан для EXECUTE EXECUTE STMT; 12:20:48 FAILED [DEALLOCATE - 0 rows, 1.248 secs] [Code: 1243, SQL State: HY000] Неизвестный обработчик подготовленных операторов (STMT) передан DEALLOCATE PREPARE освобождает подготовку STMT;
Независимо от того, какой клиент используется для выполнения этих операторов SQL, похоже, он не распознает оператор DELIMITER. Ответ изменен для дальнейшей демонстрации с использованием клиента командной строки MySQL. (В вопросе не дается никакой информации о фактическом используемом клиенте или библиотеке базы данных.)
Спасибо. Я могу исправить эту проблему. Я использовал @ перед разделителем, и это работало следующим образом: @DELIMITER %%%;