mysql: передача оператора sql в качестве параметра в хранимую процедуру для его выполнения - PullRequest
0 голосов
/ 12 июня 2018

Пожалуйста, помогите мне с моим запросом: ниже я упомянул хранимую процедуру в 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]*/

1 Ответ

0 голосов
/ 12 июня 2018

С точкой с запятой в теле процедуры, нам нужно изменить разделитель операторов для сеанса.

Например:

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 вернул aошибка синтаксиса;что является ожидаемым поведением, потому что это не допустимый оператор SQL.Выполнение следующего оператора:

PREPARE STMT FROM @sql;

вернуло ошибку, поскольку @sql оценивается как NULL.Следующий выполненный оператор

EXECUTE STMT;

не выполнен, поскольку STMT не является допустимым дескриптором оператора.(Потому что PREPARE не удалось.)


Мы не хотим выполнять SET и PREPARE как отдельные операторы, мы хотим, чтобы они были частью оператора CREATE PROCEDURE.

Проблема в том, что точка с запятой является оператором-терминатором;нам нужно изменить терминатор оператора, чтобы он был чем-то другим, на какую-то строку, которая не отображается в теле CREATE PROCEDURE.


FOLLOWUP

Ссылка: 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...