为什么游标在一次迭代后退出?
Why is the cursor exiting after one iteration?
我有一个 table,其中列出了 table 个我想要计算的数:
|dq_tbl_id|dq_tbl_tbl_name |dq_tbl_use_batch_stamp|
|---------|--------------------------|----------------------|
|1 |dev_credly_badges |1 |
|... |... |... |
|18 |tbl18 |[NULL] |
我不明白为什么程序在一次迭代后退出:
CREATE DEFINER=`channel`@`%` PROCEDURE `dq_job_dev_count`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE proc_dq_tbl_id SMALLINT;
DECLARE tbl_count INT DEFAULT 0;
DECLARE tbl_name VARCHAR(35);
DECLARE dq_tbl_use_batch_stamp BOOL DEFAULT FALSE;
DECLARE dq_tbl_ids
CURSOR FOR
SELECT dq_tbl_id FROM ref_dq_tbl_count;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN dq_tbl_ids;
WHILE done = 0 DO
FETCH NEXT FROM dq_tbl_ids INTO proc_dq_tbl_id;
IF done = 0 THEN
SELECT dq_tbl_tbl_name, dq_tbl_use_batch_stamp INTO @tbl_name, @dq_tbl_use_batch_stamp FROM ref_dq_tbl_count WHERE dq_tbl_id = @proc_dq_tbl_id;
IF @dq_tbl_use_batch_stamp = 1 THEN
SET @sql_stmt = CONCAT('SELECT COUNT(*) INTO @tbl_count FROM ', @tbl_name, ' WHERE DATE(batch_stamp) = CURDATE()');
ELSE
SET @sql_stmt = CONCAT('SELECT COUNT(*) INTO @tbl_count FROM ', @tbl_name);
END IF;
PREPARE stmt FROM @sql_stmt;
EXECUTE stmt;
INSERT INTO prod_dq_tbl_load_counts (tbl_name, row_count) VALUES (@tbl_name, @tbl_count);
END IF;
END WHILE;
CLOSE dq_tbl_ids;
END
您正在将游标结果提取到局部变量中:
FETCH NEXT FROM dq_tbl_ids INTO proc_dq_tbl_id;
随后您使用了 user-defined 变量 @proc_dq_tbl_id
,错误地认为它包含您获取的值。
在 MySQL 存储过程中,具有 @
标记的变量是您使用 DECLARE
创建的 user-defined variable. It is literally a different variable than the local variable。
您可以将游标提取到 user-defined 变量中(使用 @
标记),或者您可以将游标提取到局部变量中。但随后您必须在后续表达式中使用相同的变量。
由于 @proc_dq_tbl_id
可能为 NULL,因此您在其中使用它的 SELECT 语句将永远不会匹配任何行。您的光标可能循环了很多,但每个循环迭代中的 SELECT 语句都找不到匹配项。
MySQL 中对变量的这种处理不同于其他品牌的 SQL 数据库(例如 Microsoft SQL 服务器)。习惯使用其他品牌的开发人员有时会感到困惑。
我有一个 table,其中列出了 table 个我想要计算的数:
|dq_tbl_id|dq_tbl_tbl_name |dq_tbl_use_batch_stamp|
|---------|--------------------------|----------------------|
|1 |dev_credly_badges |1 |
|... |... |... |
|18 |tbl18 |[NULL] |
我不明白为什么程序在一次迭代后退出:
CREATE DEFINER=`channel`@`%` PROCEDURE `dq_job_dev_count`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE proc_dq_tbl_id SMALLINT;
DECLARE tbl_count INT DEFAULT 0;
DECLARE tbl_name VARCHAR(35);
DECLARE dq_tbl_use_batch_stamp BOOL DEFAULT FALSE;
DECLARE dq_tbl_ids
CURSOR FOR
SELECT dq_tbl_id FROM ref_dq_tbl_count;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN dq_tbl_ids;
WHILE done = 0 DO
FETCH NEXT FROM dq_tbl_ids INTO proc_dq_tbl_id;
IF done = 0 THEN
SELECT dq_tbl_tbl_name, dq_tbl_use_batch_stamp INTO @tbl_name, @dq_tbl_use_batch_stamp FROM ref_dq_tbl_count WHERE dq_tbl_id = @proc_dq_tbl_id;
IF @dq_tbl_use_batch_stamp = 1 THEN
SET @sql_stmt = CONCAT('SELECT COUNT(*) INTO @tbl_count FROM ', @tbl_name, ' WHERE DATE(batch_stamp) = CURDATE()');
ELSE
SET @sql_stmt = CONCAT('SELECT COUNT(*) INTO @tbl_count FROM ', @tbl_name);
END IF;
PREPARE stmt FROM @sql_stmt;
EXECUTE stmt;
INSERT INTO prod_dq_tbl_load_counts (tbl_name, row_count) VALUES (@tbl_name, @tbl_count);
END IF;
END WHILE;
CLOSE dq_tbl_ids;
END
您正在将游标结果提取到局部变量中:
FETCH NEXT FROM dq_tbl_ids INTO proc_dq_tbl_id;
随后您使用了 user-defined 变量 @proc_dq_tbl_id
,错误地认为它包含您获取的值。
在 MySQL 存储过程中,具有 @
标记的变量是您使用 DECLARE
创建的 user-defined variable. It is literally a different variable than the local variable。
您可以将游标提取到 user-defined 变量中(使用 @
标记),或者您可以将游标提取到局部变量中。但随后您必须在后续表达式中使用相同的变量。
由于 @proc_dq_tbl_id
可能为 NULL,因此您在其中使用它的 SELECT 语句将永远不会匹配任何行。您的光标可能循环了很多,但每个循环迭代中的 SELECT 语句都找不到匹配项。
MySQL 中对变量的这种处理不同于其他品牌的 SQL 数据库(例如 Microsoft SQL 服务器)。习惯使用其他品牌的开发人员有时会感到困惑。