Mysql 不使用存储过程循环n次
我如何在不使用存储过程的情况下编写在MySql中运行n次的循环 这是我如何使用存储过程实现的:Mysql 不使用存储过程循环n次,mysql,sql,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;
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 ;
如果删除存储过程并运行正常查询,则查询将失败,并出现以下错误:
1064-您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,以了解可在“DECLARE count INT DEFAULT 0”附近使用的正确语法;当第'2行的计数小于10 DO时
我已经在互联网上找到了一个解决方案,但运气不好
根据评论进行编辑:
上面的存储过程正是我想要的:它循环10次并执行我的sql语句。现在我想在不使用存储过程的情况下完成同样的事情。比如:
DECLARE count INT DEFAULT 0;
WHILE count < 10 DO
/**Sql statement**/
SET count = count + 1;
END WHILE;
MySQL文档上说:
MySQL支持IF、CASE、ITERATE、left循环、WHILE和REPEAT
存储程序中的流控制构造
文件上说:
存储程序定义包括一个可以使用复合
语句、循环、条件和声明的变量
本节介绍BEGIN。。。端化合物
语句以及可在存储的
程序:存储过程和函数、触发器和事件
复合语句是可以包含其他块的块;
变量、条件处理程序和游标的声明;和流动
控件构造,例如循环和条件测试
因此,看起来您只能在存储过程、函数或触发器中运行显式循环
根据您在SQL语句中的操作,可以使用数字表或数字视图
如果您的查询是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
插入示例
我建议在数据库中有一个永久的数字表。它在许多情况下都很有用。请参阅上面的链接,了解如何生成它
因此,如果您有一个表编号,其int column Number的值为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倍。您可以使用MariaDB序列引擎直接完成。MariaDB是MySQL的二进制替代品 序列引擎允许创建具有给定起始值、结束值和增量的正整数的升序或降序序列 [手动顺序引擎] 以下是一些示例:
mysql -uroot -p
Enter password: xxxxxxx
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 5
Server version: 10.0.20-MariaDB-log Homebrew
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use tmp
Database changed
MariaDB [tmp]> select version();
+---------------------+
| version() |
+---------------------+
| 10.0.20-MariaDB-log |
+---------------------+
1 row in set (0.00 sec)
MariaDB [tmp]> select * from seq_1_to_10;
+-----+
| seq |
+-----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+-----+
10 rows in set (0.00 sec)
MariaDB [tmp]> select * from seq_1_to_10_step_2;
+-----+
| seq |
+-----+
| 1 |
| 3 |
| 5 |
| 7 |
| 9 |
+-----+
5 rows in set (0.00 sec)
MariaDB [tmp]> SELECT DAYNAME('1980-12-05' + INTERVAL (seq) YEAR) day,
-> '1980-12-05' + INTERVAL (seq) YEAR date FROM seq_0_to_40;
+-----------+------------+
| day | date |
+-----------+------------+
| Friday | 1980-12-05 |
| Saturday | 1981-12-05 |
| Sunday | 1982-12-05 |
| Monday | 1983-12-05 |
| Wednesday | 1984-12-05 |
| Thursday | 1985-12-05 |
| Friday | 1986-12-05 |
| Saturday | 1987-12-05 |
| Monday | 1988-12-05 |
| Tuesday | 1989-12-05 |
| Wednesday | 1990-12-05 |
| Thursday | 1991-12-05 |
| Saturday | 1992-12-05 |
| Sunday | 1993-12-05 |
| Monday | 1994-12-05 |
| Tuesday | 1995-12-05 |
| Thursday | 1996-12-05 |
| Friday | 1997-12-05 |
| Saturday | 1998-12-05 |
| Sunday | 1999-12-05 |
| Tuesday | 2000-12-05 |
| Wednesday | 2001-12-05 |
| Thursday | 2002-12-05 |
| Friday | 2003-12-05 |
| Sunday | 2004-12-05 |
| Monday | 2005-12-05 |
| Tuesday | 2006-12-05 |
| Wednesday | 2007-12-05 |
| Friday | 2008-12-05 |
| Saturday | 2009-12-05 |
| Sunday | 2010-12-05 |
| Monday | 2011-12-05 |
| Wednesday | 2012-12-05 |
| Thursday | 2013-12-05 |
| Friday | 2014-12-05 |
| Saturday | 2015-12-05 |
| Monday | 2016-12-05 |
| Tuesday | 2017-12-05 |
| Wednesday | 2018-12-05 |
| Thursday | 2019-12-05 |
| Saturday | 2020-12-05 |
+-----------+------------+
41 rows in set (0.00 sec)
MariaDB [tmp]>
这里有一个例子:
MariaDB [(none)]> use tmp
Database changed
MariaDB [tmp]> SELECT * FROM seq_1_to_5,
-> (SELECT * FROM animals) AS x
-> ORDER BY seq;
+-----+------+-----------+-----------------+
| seq | id | name | specie |
+-----+------+-----------+-----------------+
| 1 | 1 | dougie | dog-poodle |
| 1 | 6 | tweety | bird-canary |
| 1 | 5 | spotty | turtle-spotted |
| 1 | 4 | mr.turtle | turtle-snapping |
| 1 | 3 | cadi | cat-persian |
| 1 | 2 | bonzo | dog-pitbull |
| 2 | 4 | mr.turtle | turtle-snapping |
| 2 | 3 | cadi | cat-persian |
| 2 | 2 | bonzo | dog-pitbull |
| 2 | 1 | dougie | dog-poodle |
| 2 | 6 | tweety | bird-canary |
| 2 | 5 | spotty | turtle-spotted |
| 3 | 6 | tweety | bird-canary |
| 3 | 5 | spotty | turtle-spotted |
| 3 | 4 | mr.turtle | turtle-snapping |
| 3 | 3 | cadi | cat-persian |
| 3 | 2 | bonzo | dog-pitbull |
| 3 | 1 | dougie | dog-poodle |
| 4 | 2 | bonzo | dog-pitbull |
| 4 | 1 | dougie | dog-poodle |
| 4 | 6 | tweety | bird-canary |
| 4 | 5 | spotty | turtle-spotted |
| 4 | 4 | mr.turtle | turtle-snapping |
| 4 | 3 | cadi | cat-persian |
| 5 | 5 | spotty | turtle-spotted |
| 5 | 4 | mr.turtle | turtle-snapping |
| 5 | 3 | cadi | cat-persian |
| 5 | 2 | bonzo | dog-pitbull |
| 5 | 1 | dougie | dog-poodle |
| 5 | 6 | tweety | bird-canary |
+-----+------+-----------+-----------------+
30 rows in set (0.00 sec)
MariaDB [tmp]>
这是不可能的
我阅读了所有MySQL文档,发现句子只能在函数/过程体中声明。正如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;
这段代码对我有用。我对mysql一无所知,但这难道不是因为在保留关键字中计数吗?@HoneyBadger我尝试了另一个名称,它不起作用。不清楚你想要什么。你有你的存储过程,你调用你的过程。然后删除该过程并运行正常查询,如SELECT 10?如果是这样,你将永远不会收到你发布的错误消息。让我们看看您试图运行的查询。我知道,它并不能真正回答问题,但您的主要查询是做什么的?也许可以将其重写为一个没有显式循环的单一查询。@JuanCarlosOropeza我的sql语句是一个基本的插入查询,就像插入到表\u namecol1,col2,col3 VALUESval1,val2,count感谢Bernd,但我看不出在本例中你在哪里进行While循环/迭代序列引擎为你做这件事。如果使用像seq_from_to_step这样的表名,则会创建for循环。。您可以直接使用select*从序列1到序列10。我会编辑我的答案。很漂亮!因为我使用Maria,这是一种比其他方法更好的方法。我正准备接受它并为一件事编写一个存储过程。。。生成20个uuid。从序列1到序列20中选择UUID更好!我也应该好好研究一下他们的其他引擎。我可能错过了一些好东西,因为我晚会迟到了。我可以问一个问题吗?目前我有一个类似于OP的请求,但是我只有MySQL数据库的Select权限。可以用Mariadb连接到它吗?有可能获得gui界面吗?非常感谢。您在回答中遗漏了先决条件:1将数据库从MySQL迁移到Maria 2卸载MySQL 3安装Maria 4更新自己的代码以使用Maria库进行连接5使用新数据库测试软件6修复不兼容7将新版本部署到服务器。最后你可以使用序列引擎@卢特,谢谢你。您也可以将数字表与INSERT一起使用。您可以编写一条语句,一次插入10行,而不是一个循环中的10条独立语句
只需要一个查询就可以了?@LuthandoLoot,我为INSERT添加了一个示例。
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;
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