循环n次而不使用存储过程

时间:2015-09-03 05:57:33

标签: mysql sql

如何在不使用存储过程的情况下编写在MySql中运行n次的循环。

这是我使用存储过程的方法:

DELIMITER $$
DROP PROCEDURE IF EXISTS test$$
CREATE PROCEDURE test()
BEGIN
   DECLARE count INT DEFAULT 0;
   WHILE count < 10 DO
      /**Sql statement**/
      SET count = count + 1;
   END WHILE;
END$$
DELIMITER ;  

然后我以这种方式执行我的程序:

call test();  

如果我删除存储过程并运行正常查询,则它会因此错误而失败:

  

1064 - 您的SQL语法出错;检查与您的MySQL服务器版本相对应的手册,以获得正确的语法,以便在DECLARE计数附近使用INT DEFAULT 0;数量&lt; 10 DO在线&#39; 2

我已经通过互联网查找了没有运气的解决方案。

根据评论进行编辑:

上面的存储过程完全符合我的要求:它循环10次并执行我的sql语句。现在我想在不使用存储过程的情况下完成同样的事情。类似的东西:

DECLARE count INT DEFAULT 0;
   WHILE count < 10 DO
      /**Sql statement**/
      SET count = count + 1;
   END WHILE;  

4 个答案:

答案 0 :(得分:12)

Flow Control Statements上的MySQL文档说:

  

MySQL支持IF,CASE,ITERATE,LEAVE LOOP,WHILE和REPEAT   流程控制的构造在存储的程序中

Stored Programs and Views上的文档说:

  

存储的程序定义包括可能使用化合物的主体   语句,循环,条件和声明的变量

Compound-Statement Syntax

  

本节介绍BEGIN ... END化合物的语法   语句和其他语句可以在存储的主体中使用   程序:存储过程和函数,触发器和事件。

     

复合语句是一个可以包含其他块的块;   变量,条件处理程序和游标的声明;并且流动   控制构造,如循环和条件测试。

因此,看起来您只能在存储过程,函数或触发器中运行显式循环。

根据您在SQL语句中的操作,可以使用数字表(或视图)(Creating a "Numbers Table" in mysqlMYSQL: Sequential Number Table)。

如果您的查询是SELECT并且可以将SELECT的结果作为一个长结果集返回10次(而不是10个单独的结果集),则可以执行以下操作:

SELECT MainQuery.*
FROM
    (
        SELECT 1 AS Number 
        UNION ALL SELECT 2
        UNION ALL SELECT 3
        UNION ALL SELECT 4
        UNION ALL SELECT 5
        UNION ALL SELECT 6
        UNION ALL SELECT 7
        UNION ALL SELECT 8
        UNION ALL SELECT 9
        UNION ALL SELECT 10
    ) AS Numbers
    CROSS JOIN
    (
        SELECT 'some data' AS Result
    ) AS MainQuery

INSERT示例

我建议在数据库中有一个永久的数字表。在许多情况下它很有用。请参阅上面的链接如何生成它。

因此,如果您的表Numbers intNumber的值为1到100K(就像我一样),并且此列上有主键,那么而不是这个循环:

DECLARE count INT DEFAULT 0;
WHILE count < 10 DO
    INSERT INTO table_name(col1,col2,col3) 
    VALUES("val1","val2",count);

    SET count = count + 1;
END WHILE;

你可以写:

INSERT INTO table_name(col1,col2,col3)
SELECT ("val1", "val2", Numbers.Number-1)
FROM Numbers
WHERE Numbers.Number <= 10;

它的工作速度也快了近10倍。

答案 1 :(得分:1)

这是不可能的。

我阅读了所有MySQL文档,它只能在函数/过程体中声明。

答案 2 :(得分:1)

DECLARE @count INT = 0;

   WHILE @count < 10 
    BEGIN
     DELETE TOP (300)
     FROM EmployeeInformation
     WHERE IsSynced=1 and CreatedDate<'2020-02-29'
     SET @count = @count + 1;
   END

此代码对我有用。

答案 3 :(得分:0)

正如Berd所提到的,您可以使用内置顺序执行此操作,但这有点奇怪:

SET @i = 1;
set @str = 'a,b,c,d,e,f,g,h';

select temp.length into @length from 
(select
        ROUND(   
            (
                LENGTH(dt.data)
                - LENGTH( REPLACE (dt.data, ",", "") ) 
            ) / LENGTH(",")        
        )+1 AS length   
     from (select @str as data) dt
 ) temp;

SET @query = CONCAT('select substring_index(
    substring_index(@str, '','', seq), 
    '','', 
    -1
  ) as letter from seq_', @i, '_to_',@length);

PREPARE q FROM @query;
EXECUTE q;