Я пытаюсь использовать курсор для обработки строк, содержащих строку:
CREATE PROCEDURE REVERT_ALL(IN TABLE_NAME VARCHAR(255))
BEGIN
DECLARE bDone INT;
DECLARE CH_ID INT;
DECLARE CH_CHANGE CHAR;
DECLARE curs cursor for
SELECT 'table_id', 'change_type' FROM mysql_snapshot.db_changes where 'table_name' = "rooms";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN curs;
insert into splog set text = concat('SELECT id, 'table_name', table_id, 'change_type' FROM mysql_snapshot.db_changes where table_name = ',TABLE_NAME, ';');
SET bDone = 0;
REPEAT
FETCH curs INTO CH_ID, CH_CHANGE;
insert into splog set text = concat_ws( ' -- ', 'CH_ID ', CH_ID,' TABLE ',TABLE_NAME, ' CH_CHANGE ', CH_CHANGE);
UNTIL bDone END REPEAT;
CLOSE curs;
END;
По какой-то причине, которую я ищу большую часть дня,
where 'table_name' = "rooms"
кажется, игнорируется. План состоит в том, чтобы изменить его на
where 'table_name' = TABLE_NAME
для использования аргумента процедуры. Я просто получаю все строки. Вставки для ведения журнала и отладки.
У вас есть двусмысленность между именем параметра процедуры TABLE_NAME
и именем таблицы table_name
. Его следует избегать, поскольку он вызывает неясные проблемы, подобные этому.
В этом случае внутри процедуру, TABLE_NAME
, table_name
и table_name
в обратных кавычках все интерпретируются как локальное переменное имя (имя параметра). Итак, ваше условие 'where table_name = ',TABLE_NAME
всегда истинно; и когда вы заменяете TABLE_NAME
"rooms"
, условие всегда истинно, если вы вызываете процедуру с "rooms"
в качестве аргумента и всегда всегда ложны. Рассмотрим этот упрощенный пример:
DROP PROCEDURE IF EXISTS pr;
DROP TABLE IF EXISTS t;
CREATE PROCEDURE pr (IN TABLE_NAME VARCHAR(255))
SELECT 'id', 'table_name', TABLE_NAME FROM t
;
CREATE TABLE t (id INT, 'table_name' VARCHAR(255));
INSERT INTO t VALUES (1,'hotels'),(2,'rooms');
CALL pr("rooms");
CALL pr("foo");
Ты получишь
MariaDB [test]> CALL pr("rooms");
+------+--------------+------------+
| id | 'table_name' | TABLE_NAME |
+------+--------------+------------+
| 1 | rooms | rooms |
| 2 | rooms | rooms |
+------+--------------+------------+
2 rows in set (0.00 sec)
MariaDB [test]> CALL pr("foo");
+------+--------------+------------+
| id | 'table_name' | TABLE_NAME |
+------+--------------+------------+
| 1 | foo | foo |
| 2 | foo | foo |
+------+--------------+------------+
2 rows in set (0.00 sec)
Как видите, независимо от аргумента table_name
всегда равно TABLE_NAME
, для всех строк.
Теперь, если вы замените TABLE_NAME
на явные "rooms"
:
DROP PROCEDURE IF EXISTS pr;
DROP TABLE IF EXISTS t;
CREATE PROCEDURE pr (IN TABLE_NAME VARCHAR(255))
SELECT 'id', 'table_name', "rooms" FROM t
;
CREATE TABLE t (id INT, 'table_name' VARCHAR(255));
INSERT INTO t VALUES (1,'hotels'),(2,'rooms');
CALL pr("rooms");
CALL pr("foo");
Теперь условие table_name = "rooms"
будет истинным для первого вызова, для всех строк и false для второго вызова для всех строк:
MariaDB [test]> CALL pr("rooms");
+------+--------------+-------+
| id | 'table_name' | rooms |
+------+--------------+-------+
| 1 | rooms | rooms |
| 2 | rooms | rooms |
+------+--------------+-------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> CALL pr("foo");
+------+--------------+-------+
| id | 'table_name' | rooms |
+------+--------------+-------+
| 1 | foo | rooms |
| 2 | foo | rooms |
+------+--------------+-------+
2 rows in set (0.00 sec)
Вместо этого вам нужно другое имя для параметра:
DROP PROCEDURE IF EXISTS pr;
DROP TABLE IF EXISTS t;
CREATE PROCEDURE pr (IN T_NAME VARCHAR(255))
SELECT 'id', 'table_name', T_NAME FROM t
;
CREATE TABLE t (id INT, 'table_name' VARCHAR(255));
INSERT INTO t VALUES (1,'hotels'),(2,'rooms');
CALL pr("rooms");
CALL pr("foo");
Теперь сравнение table_name = T_NAME
действительно имеет смысл;
MariaDB [test]> CALL pr("rooms");
+------+------------+--------+
| id | table_name | T_NAME |
+------+------------+--------+
| 1 | hotels | rooms |
| 2 | rooms | rooms |
+------+------------+--------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> CALL pr("foo");
+------+------------+--------+
| id | table_name | T_NAME |
+------+------------+--------+
| 1 | hotels | foo |
| 2 | rooms | foo |
+------+------------+--------+
2 rows in set (0.00 sec)
`table_name` = "rooms"
игнорируется`table_name` = TABLE_NAME
игнорируется?