Return 来自使用 CURSOR/LOOP 的存储过程的单个集合中的数据
Return data in the single set from stored procedure using CURSOR/LOOP
我想 return 单组数据,但是我在单行中得到 10 个不同的输出。我想在一组中有 10 行:
DROP TABLE IF EXISTS calendar;
DROP PROCEDURE IF EXISTS p_generate_snapshot;
CREATE TABLE calendar(date date);
INSERT INTO calendar(date) VALUES
('2020-11-01'),
('2020-11-02'),
('2020-11-03'),
('2020-11-04'),
('2020-11-05'),
('2020-11-06'),
('2020-11-07'),
('2020-11-08'),
('2020-11-09'),
('2020-11-10');
DELIMITER $$
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
DECLARE d date;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_name CURSOR FOR SELECT * FROM calendar c WHERE date >= start_date AND date < end_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_name;
fetch_loop: LOOP
FETCH cursor_name INTO d;
IF done THEN
LEAVE fetch_loop;
END IF;
SELECT d;
END LOOP;
CLOSE cursor_name;
END$$
DELIMITER ;
CALL p_generate_snapshot('20201101', '20201201');
不清楚为什么要为此使用游标。你的程序可以写成:
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
SELECT * FROM calendar c WHERE date >= start_date AND date < end_date;
END
这将 return 一个结果集,如您所说。
但您的示例可能已被简化,并且您需要执行其他步骤来处理游标获取的行。这将是使用游标的正当理由。
但我认为不可能 return 游标处理的行就好像它是一个结果集一样。当然,不可能在游标循环的每次迭代中都通过 SELECT d;
来完成。正如您所发现的那样,这必然会 return 每行一个单独的结果集。
一种解决方法是在游标循环期间将行插入到临时 table 中,尽管它很笨拙。然后 select 从温度 table 作为最后一步。
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
DECLARE _d date;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_name CURSOR FOR SELECT date FROM calendar c WHERE date >= start_date AND date < end_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE t (d DATE);
OPEN cursor_name;
fetch_loop: LOOP
FETCH cursor_name INTO _d;
IF done THEN
LEAVE fetch_loop;
END IF;
INSERT INTO t SET d = _d;
END LOOP;
CLOSE cursor_name;
SELECT d FROM t;
DROP TABLE t;
END
就此而言,我完全不知道您为什么要使用过程,而不仅仅是在客户端应用程序中使用 运行 那个 SELECT 语句。这将解决这两个问题——逐行处理,但仍将其视为单个查询结果。
我几乎从不使用 MySQL 中的存储过程。我发现它们确实比它们的价值更麻烦。我在这里发布了原因:https://www.quora.com/What-are-the-reasons-not-to-use-or-not-use-stored-procedures/answer/Bill-Karwin
我想 return 单组数据,但是我在单行中得到 10 个不同的输出。我想在一组中有 10 行:
DROP TABLE IF EXISTS calendar;
DROP PROCEDURE IF EXISTS p_generate_snapshot;
CREATE TABLE calendar(date date);
INSERT INTO calendar(date) VALUES
('2020-11-01'),
('2020-11-02'),
('2020-11-03'),
('2020-11-04'),
('2020-11-05'),
('2020-11-06'),
('2020-11-07'),
('2020-11-08'),
('2020-11-09'),
('2020-11-10');
DELIMITER $$
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
DECLARE d date;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_name CURSOR FOR SELECT * FROM calendar c WHERE date >= start_date AND date < end_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_name;
fetch_loop: LOOP
FETCH cursor_name INTO d;
IF done THEN
LEAVE fetch_loop;
END IF;
SELECT d;
END LOOP;
CLOSE cursor_name;
END$$
DELIMITER ;
CALL p_generate_snapshot('20201101', '20201201');
不清楚为什么要为此使用游标。你的程序可以写成:
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
SELECT * FROM calendar c WHERE date >= start_date AND date < end_date;
END
这将 return 一个结果集,如您所说。
但您的示例可能已被简化,并且您需要执行其他步骤来处理游标获取的行。这将是使用游标的正当理由。
但我认为不可能 return 游标处理的行就好像它是一个结果集一样。当然,不可能在游标循环的每次迭代中都通过 SELECT d;
来完成。正如您所发现的那样,这必然会 return 每行一个单独的结果集。
一种解决方法是在游标循环期间将行插入到临时 table 中,尽管它很笨拙。然后 select 从温度 table 作为最后一步。
CREATE PROCEDURE p_generate_snapshot(start_date date, end_date date)
BEGIN
DECLARE _d date;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_name CURSOR FOR SELECT date FROM calendar c WHERE date >= start_date AND date < end_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE t (d DATE);
OPEN cursor_name;
fetch_loop: LOOP
FETCH cursor_name INTO _d;
IF done THEN
LEAVE fetch_loop;
END IF;
INSERT INTO t SET d = _d;
END LOOP;
CLOSE cursor_name;
SELECT d FROM t;
DROP TABLE t;
END
就此而言,我完全不知道您为什么要使用过程,而不仅仅是在客户端应用程序中使用 运行 那个 SELECT 语句。这将解决这两个问题——逐行处理,但仍将其视为单个查询结果。
我几乎从不使用 MySQL 中的存储过程。我发现它们确实比它们的价值更麻烦。我在这里发布了原因:https://www.quora.com/What-are-the-reasons-not-to-use-or-not-use-stored-procedures/answer/Bill-Karwin