为什么这个 SQL PREPARE .. EXECUTE 在 MySQL 8 中给出语法错误但在 MariaDB 中没有
Why does this SQL PREPARE .. EXECUTE give a syntax error in MySQL 8 but not in MariaDB
是的,还有一个关于移植代码的问题!
我的 ISP 有 'upgraded' 从 MariaDB 10.4 到 MySQL 8.0,我现在必须调整很多以前工作的代码。以下存储过程在 MariaDB 中 运行 没有错误,但在 MySQL8 中我在 PREPARE
/ EXECUTE
附近遇到语法错误。实际错误是
Error Code: 1064
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
'sql_string;
EXECUTE do_update;
END LOOP update_table; -- her' at line 32
任何人都可以建议 MySQL 的正确语法吗?
(它可能是 CONCAT,但它看起来正确并且在 MariaDB 中始终有效)
程序定义如下,接近尾声报语法错误
DELIMITER $$
CREATE PROCEDURE `redact_member_id_in_all_tables`( member_id_to_replace INT, redacted_member_id INT )
BEGIN
DECLARE finished INT;
DECLARE sql_string TEXT;
DECLARE the_table_name TEXT;
-- declare cursor for a data set containing all the base table names that have a column 'memberID
-- see https://dataedo.com/kb/query/mariadb/find-tables-with-specific-column-name
DECLARE table_cursor CURSOR FOR
SELECT tab.table_name
FROM information_schema.tables AS tab
INNER JOIN information_schema.columns AS col
ON col.table_schema = tab.table_schema
AND col.table_name = tab.table_name
AND column_name = 'member_id'
WHERE tab.table_type = 'BASE TABLE';
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
SET finished = 0;
-- open the data set containing the table name
OPEN table_cursor;
update_table: LOOP -- 'update_table:' is a label identifying this loop
FETCH table_cursor INTO the_table_name; -- get one table name
IF finished = 1 THEN
LEAVE update_table;
END IF;
-- build update statment list
SET sql_string = CONCAT('UPDATE ', the_table_name, ' SET member_id = ', redacted_member_id, ' WHERE member_id = ', member_id_to_replace) ;
PREPARE do_update FROM sql_string;
EXECUTE do_update;
END LOOP update_table; -- here we use the label to show which loop we are ending
CLOSE table_cursor; -- release the memory associated with the cursor
END$$
DELIMITER ;
看来 mysql 只支持从用户变量而不是存储过程变量进行 PREPARE。尝试:
SET @sql_string = sql_string;
PREPARE do_update FROM @sql_string;
https://dev.mysql.com/doc/refman/8.0/en/prepare.html:
PREPARE stmt_name FROM preparable_stmt
...
preparable_stmt is either a string literal or a user variable
(虽然有趣的是 mariadb doc 说了同样的事情,甚至强调不能使用已声明的变量;这让我觉得 mariadb 得到了增强以允许它,但文档没有改变。)
是的,还有一个关于移植代码的问题!
我的 ISP 有 'upgraded' 从 MariaDB 10.4 到 MySQL 8.0,我现在必须调整很多以前工作的代码。以下存储过程在 MariaDB 中 运行 没有错误,但在 MySQL8 中我在 PREPARE
/ EXECUTE
附近遇到语法错误。实际错误是
Error Code: 1064
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
'sql_string;
EXECUTE do_update;
END LOOP update_table; -- her' at line 32
任何人都可以建议 MySQL 的正确语法吗?
(它可能是 CONCAT,但它看起来正确并且在 MariaDB 中始终有效)
程序定义如下,接近尾声报语法错误
DELIMITER $$
CREATE PROCEDURE `redact_member_id_in_all_tables`( member_id_to_replace INT, redacted_member_id INT )
BEGIN
DECLARE finished INT;
DECLARE sql_string TEXT;
DECLARE the_table_name TEXT;
-- declare cursor for a data set containing all the base table names that have a column 'memberID
-- see https://dataedo.com/kb/query/mariadb/find-tables-with-specific-column-name
DECLARE table_cursor CURSOR FOR
SELECT tab.table_name
FROM information_schema.tables AS tab
INNER JOIN information_schema.columns AS col
ON col.table_schema = tab.table_schema
AND col.table_name = tab.table_name
AND column_name = 'member_id'
WHERE tab.table_type = 'BASE TABLE';
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
SET finished = 0;
-- open the data set containing the table name
OPEN table_cursor;
update_table: LOOP -- 'update_table:' is a label identifying this loop
FETCH table_cursor INTO the_table_name; -- get one table name
IF finished = 1 THEN
LEAVE update_table;
END IF;
-- build update statment list
SET sql_string = CONCAT('UPDATE ', the_table_name, ' SET member_id = ', redacted_member_id, ' WHERE member_id = ', member_id_to_replace) ;
PREPARE do_update FROM sql_string;
EXECUTE do_update;
END LOOP update_table; -- here we use the label to show which loop we are ending
CLOSE table_cursor; -- release the memory associated with the cursor
END$$
DELIMITER ;
看来 mysql 只支持从用户变量而不是存储过程变量进行 PREPARE。尝试:
SET @sql_string = sql_string;
PREPARE do_update FROM @sql_string;
https://dev.mysql.com/doc/refman/8.0/en/prepare.html:
PREPARE stmt_name FROM preparable_stmt ... preparable_stmt is either a string literal or a user variable
(虽然有趣的是 mariadb doc 说了同样的事情,甚至强调不能使用已声明的变量;这让我觉得 mariadb 得到了增强以允许它,但文档没有改变。)