MySQL 准备语句 - 如何循环

2024-04-02

我有一个充满 ID 号的表,我需要循环遍历该表,并将其用作准备好的语句中的变量。我不知道是否需要为此使用存储过程,或者常规查询是否可以做到这一点。这是一个简单的例子。

SELECT id from var_list;

loop through @ID = var_list.id ....


SET @s1 = "SELECT * FROM data WHERE id = @ID"; 
PREPARE stmt1 FROM @s1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

正如评论中提到的,我只需要它来导出一些数据,我的表中有大约 50-100 个 ID,并且编写了一个查询来一次将一个文件导出到服务器。

编辑 我计划使用类似......的东西将每次迭代的结果转储到文件中。

INTO OUTFILE '/tmp/orders.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'

正如其他人已经建议的那样,我们通常avoid循环遍历结果集RBAR(逐行排列)主要是出于性能原因。我们只是不想养成循环结果集的习惯。但这并不能回答你提出的问题。

为了回答您提出的问题,这里有一个 MySQL 存储程序的基本示例,该程序使用 CURSOR 单独处理查询返回的行。 MySQL 不支持匿名块,因此唯一的方法是在 MySQL 存储程序中,例如 PROCEDURE

DELIMITER $$

CREATE PROCEDURE loop_through_var_list
BEGIN
   DECLARE done INT DEFAULT 0;
   DECLARE v_id INT DEFAULT NULL;  
   DECLARE csr_var_list CURSOR FOR SELECT id FROM var_list ORDER BY id;
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
   OPEN csr_var_list;
   get_id: LOOP
      FETCH csr_var_list INTO v_id; 
      IF done = 1 THEN
         LEAVE get_id;
      END IF;

      -- at this point, we have an id value in v_id, so we can do whatever
      SET @s1 = CONCAT('SELECT ... WHERE id =''', v_id, ''' ...');


   END LOOP get_id;
   CLOSE csr_var_list;
END$$

DELIMITER ;

要执行该过程:

CALL loop_through_var_list();

注意:MySQL 中处理 CURSOR 的语法与其他数据库有很大不同。

为了获得“循环”,我们需要使用LOOP ... END LOOP构造。

但为了防止该循环永远运行,我们需要一个 LEAVE 语句来允许我们退出循环。

我们使用条件测试来确定何时离开。在此示例中,我们希望在处理完最后一行后退出。

The FETCH当没有更多的行可供获取时,将引发异常。

我们在 CONTINUE HANDLER 中“捕获”该异常(由于某些神秘的原因,“处理程序”必须声明最后的内容;如果我们尝试在 HANDLER 之后声明某些内容(而不是另一个 HANDLER),MySQL 会抛出错误。)

当 MySQL 抛出“no more rows”异常时,会触发处理程序代码。在此示例中,我们只是设置一个变量(名为done) 到一个值。

由于它是一个“继续”处理程序,因此处理会在引发异常的语句处重新开始,在本例中,这将是 FETCH 之后的语句。因此,我们要做的第一件事就是检查我们是否“完成”。如果我们“完成”,那么我们退出循环,并关闭光标。

否则,我们知道我们有一个id价值来自var_list存储在名为的过程变量中v_id。所以现在我们可以做任何我们想做的事。看起来您想将一些 SQL 文本放入用户定义的变量中(包括将 v_id 的值放入 SQL 文本中,然后 PREPARE、EXECUTE 和 DEALLOCATE PREPARE。

请务必声明v_id具有适当数据类型的变量,该变量与id列于var_list,我只是假设它是一个 INT。

当我们到达循环末尾时,MySQL“循环”回到循环的开头,然后再次开始。

在循环体中,您可能需要将 v_id CONCAT 到要执行的 SQL 文本中。看起来您已经掌握了 PREPARE、DEALLOCATE 准备。为了进行测试,您可能需要在游标声明中的 SELECT 上添加 LIMIT 子句,然后执行简单的 SELECT v_id;在正文中,只是为了在添加更多代码之前验证循环是否正常工作。


FOLLOWUP

我想提到该任务的另一种替代方法,即基于模板运行一系列语句,替换单个 SQL select 语句提供的值...

例如,如果我有这个模板:

SELECT * 
  INTO OUTFILE '/tmp/[email protected] /cdn-cgi/l/email-protection'
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
FROM data 
WHERE id = @ID
ORDER BY 1 

我需要将出现的 @ID 替换为 SELECT 语句返回的列表中的特定 id 值,例如

SELECT id
  FROM var_list
 WHERE id IS NOT NULL
 GROUP BY id

我可能不会使用带有 CURSOR 循环的 MySQL 存储程序,我会使用不同的方法。

我将使用 SELECT 语句来生成一组可以执行的 SQL 语句。假设id是整数类型,我可能会这样做:

SELECT CONCAT(' SELECT * 
                   INTO OUTFILE ''/tmp/orders_',s.id,'.csv''
                   FIELDS TERMINATED BY '','' ENCLOSED BY ''"''
                   LINES TERMINATED BY ''\n''
                FROM data
               WHERE id = ',s.id,'
               ORDER BY 1;') AS `stmt`
 FROM ( SELECT v.id
          FROM var_list v
         WHERE v.id IS NOT NULL
         GROUP BY v.id
      ) s
ORDER BY s.id

对于每个值id从返回s,该语句返回可以(并且需要)执行的 SQL SELECT 语句的文本。将其捕获到文本文件中将为我提供一个可以运行的 SQL 脚本。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL 准备语句 - 如何循环 的相关文章

  • 数据读取过程中遇到致命错误

    我正在进行定期更新表扫描 Using connect1 As New MySqlConnection ConnectLocalhost serverString connect1 Open Dim cmd New MySqlCommand
  • 您可以使用 MySQL 查询来完整创建数据库的副本吗

    我有一个包含 5 个表的 MySQL 数据库的实时版本和一个测试版本 我不断使用 phpMyAdmin 将实时版本中的每个表复制到测试版本 有谁有mysql查询语句来制作数据库的完整副本吗 查询字符串需要考虑结构 数据 自动增量值以及与需要
  • Mac OSX 10.6 上的 Python mysqldb 不工作

    我正在使用 Python 2 7 并尝试让 Django 项目在 MySQL 后端运行 我已经下载了 mysqldb 并按照此处的指南进行操作 http cd34 com blog programming python mysql pyth
  • Google BigQuery,使用“unnest”函数时丢失了空行

    StandardSQL WITH tableA AS SELECT T001 T002 T003 AS T id 1 5 AS L id UNION ALL SELECT T008 T009 AS T id NULL AS L id SEL
  • Allen Browne 的 ConcatRelated() 错误 3061:参数太少

    我正在尝试创建给定仓库的产品列表 Allen Browne 的 ConcatRelated 函数似乎是在链接变量相同时创建列表的经过验证的正确方法 但我无法让它工作 我已将我的信息分解为单个查询 qry Products SELECT qr
  • SQL Server 每年的第一个星期一

    如何使用 T SQL 查找 一年中的第一个星期一 这是 ngruson 发布的链接中的示例 http sqlbump blogspot nl 2010 01 first monday of year html http sqlbump bl
  • Android 中读取未提交的事务

    我正在进行大量数据库操作 这会向我的数据库添加大约 10 000 条记录 由于这可能需要很长时间 因此最好使用事务 db startTransaction do write operations db setTransactionSucce
  • 连接两个表而不返回不需要的行

    我的表结构如下所示 tbl users tbl issues userid real name issueid assignedid creatorid 1 test 1 1 1 1 2 test 2 2 1
  • 如何创建包含多列MD5的GENERATED列?

    我尝试在 PostgreSQL 14 3 中添加下表 CREATE TABLE client cache id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY request VARCHAR
  • MySQL 5:我的 GROUP BY 字段的顺序重要吗?

    Peeps 我的 MySQL 查询中有一些聚合 计算字段 我的 GROUP BY 子句是动态生成的 具体取决于用户在 Web 表单中选择的选项 很好奇 GROUP BY 子句中列出的字段顺序是否会对计算产生任何影响 例如 SUM AVERA
  • 不能简单地使用 PostgreSQL 表名(“关系不存在”)

    我正在尝试运行以下 PHP 脚本来执行简单的数据库查询 db host localhost db name showfinder username user password password dbconn pg connect host
  • 单个查询删除并显示重复记录

    采访中提出的问题之一是 一张表有100条记录 其中 50 个 是重复的 是否可以用单个 查询删除重复记录 从表中以及选择和 显示剩余 50 条记录 这可以在单个 SQL 查询中实现吗 Thanks SNA 对于 SQL Server 你会使
  • 从 SQL 数据库获取日期时间

    我的数据库表中有一个 DateTime 记录 我编写一个查询从数据库中获取它 string command2 select Last Modified from Company Data where Company Name Descrip
  • 从 Presto 中的 JSON 列获取特定值

    我有一个带有 JSON 列的表points其中一行为 0 0 2 1 1 2 2 0 5 15 1 2 20 0 7 我想获取键的值 1 and 20 并将它们存储为别名 例如first and second在查询中 到目前为止我所做的是
  • SQL Server 2008 中的全文搜索一步一步

    如何开始使用SQL Server 2008 中的全文搜索 阅读这些链接 SQL SERVER 2008 创建全文目录和全文搜索 http blog sqlauthority com 2008 09 05 sql server creatin
  • 处理大数据表时应该如何使用Hibernate Mapping

    问题定义 我有一个包含大量数据 超过 100 000 行 的数据库表 表结构如下 AppID DocID DocStatus 1 100 0 1 101 1 2 200 0 2 300 1 每个 applicationID 可能有数千个文档
  • 条件对列表的 In 子句

    有一个表 我需要通过在配对值列表中应用和条件来获取分页记录 下面是解释 假设我有一堂课Billoflading其中有各个领域 表中两个重要字段是 tenant billtype 我有一个包含值的对列表 tenant1 billtype1 t
  • 如何使用Python3.4在tornado中进行异步mysql操作?

    我现在使用Python3 4 我想在Tornado中使用异步mysql客户端 我已经发现torndb https github com bdarnell torndb但在阅读其源代码后 我认为它无法进行异步mysql操作 因为它只是封装了M
  • 如何在postgresql中编写有关最大行数的约束?

    我认为这是一个很常见的问题 我有一张桌子user id INT 和一张桌子photo id BIGINT owner INT 所有者是一个参考user id 我想向表照片添加一个约束 以防止每个用户将超过 10 张照片输入数据库 写这个的最
  • 火鸟删除速度很慢

    我正在做这个简单的交易 DELETE FROM ominve01 WHERE CVE OBS IN SELECT CVE OBS FROM minve01 M WHERE M FECHA DOCU lt 31 12 2010 OR FECH

随机推荐