【问题标题】:looping through result rows and storing column data into stored procedure variables mysql遍历结果行并将列数据存储到存储过程变量mysql中
【发布时间】:2012-10-04 08:12:32
【问题描述】:

我正在尝试学习 mysql 中的存储过程。我知道下面的示例不需要 SP,但这仅用于我的学习目的 - 只是为了了解如何循环遍历行,并选择行内的特定列数据。

假设表上的 SELECT 从我的表中返回 5 条记录,结构如下 -

表名:t1 列:c1,c2,c3

我想遍历 5 行中的每一行,对于每一行,我想将列单元格数据存储到 SP 变量 varc1、varc2、varc3 中,以便 varc1 = c1、varc2 = c2、varc3 = c3。我将在循环内使用这些 varc1、varc2、varc3 进行进一步计算。

我假设需要一个存储过程,但我没有获得进行行迭代然后从循环中考虑的行中的每一列中选取数据的方法。

对 mysql/ 存储过程很陌生。 谢谢!

【问题讨论】:

    标签: mysql loops stored-procedures


    【解决方案1】:

    您似乎知道,您的要求是对大多数问题的特别低效的解决方案。但是,由于您特别要求它,并且(非常偶尔)这是解决问题的唯一方法(或者您个人有时间弄清楚如何解决它的唯一方法)。以下是您可以按照您的要求执行的操作:

    创建您的 t1 表,例如:

    CREATE TABLE t1(id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, C1 INT, C2 INT, C3 INT);
    

    执行您描述的 SELECT,例如:

    INSERT INTO  t1 SELECT NULL,c1,c2,c3 FROM the_table; 
    

    现在这是您的 Row-By-Agonising-Row “ReeBAR” 低效率存储过程:

    为您的过程准备空间并设置分隔符:

    DROP PROCEDURE IF EXISTS ReeBAR;
    DELIMITER ;;
    

    写下你的程序:

    CREATE PROCEDURE ReeBAR()
    BEGIN
    DECLARE n INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    DECLARE varc1 INT DEFAULT 0;
    DECLARE varc2 INT DEFAULT 0;
    DECLARE varc3 INT DEFAULT 0;
    SELECT COUNT(*) into n FROM t1;
    set i=1;
    WHILE i<=n DO 
      SELECT c1 FROM t1 WHERE id=i INTO varc1; 
      SELECT c2 FROM t1 WHERE id=i INTO varc2;
      SELECT c3 FROM t1 WHERE id=i INTO varc3;
      --queries which couldnt be made into set based queries go here---
      SET i = i + 1;
    END WHILE;
    End;
    

    或者,如果您的 id 列不连续,您可以使用以下光标形式。

    CREATE PROCEDURE ReeBAR()
    BEGIN
      DECLARE cursor_ID INT;
      DECLARE cursor_VAL VARCHAR;
      DECLARE done INT DEFAULT FALSE;
      DECLARE cursor_i CURSOR FOR SELECT c1,c2,c3 FROM t1;
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
      DECLARE varc1 INT DEFAULT 0;
      DECLARE varc2 INT DEFAULT 0;
      DECLARE varc3 INT DEFAULT 0;
      OPEN cursor_i;
      read_loop: LOOP
        FETCH cursor_i INTO varc1, varc2, varc3;
        IF done THEN
          LEAVE read_loop;
        END IF;
        --queries which couldnt be made into set based queries go here---
      END LOOP;
      CLOSE cursor_i;
    END;
    

    不要忘记“结束”您使用的过程并重置分隔符

    ;;
    DELIMITER ;
    

    最后运行你的 ReBAR 程序

    CALL ReeBAR();
    

    (未经测试的代码)

    【讨论】:

    • 如果 id 中存在不连续性(例如执行 DELETE 时),这将不起作用。
    • @singe3 为什么id列会有不连续性?在这种情况下,它使用自动增量生成。对于想要将该概念应用于已经存在并且可能具有不连续 id 列的表的用户来说,我已经编辑了答案以允许他们使用。
    • 感谢您的更新!实际上,如果使用数据库的应用程序出于某种原因需要删除一些旧条目,则可能会发生不连续性。
    • 您实际上可以使用while循环并通过像这样玩限制来获取任何不连续的ID:SELECT c1 FROM t1 LIMIT i,1 INTO varc1;希望对您有所帮助
    【解决方案2】:

    使用 CURSORS 和循环对其进行迭代。 http://dev.mysql.com/doc/refman/5.0/en/cursors.html。希望这会有所帮助!

    【讨论】:

    • MySQL 文档太糟糕了,以至于指向它的链接很少有用。
    猜你喜欢
    • 2017-07-16
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多