`
HuNanPengdake
  • 浏览: 235776 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Mysql 游标使用动态变量

阅读更多
从语法上来讲DECLARE cur CURSOR for语句必须写在SET @sqlstr前面,这就意味着不能通过先执行一条动态语句根据结果拼凑游标的内容,而且游标在定义的时候也没有参数的概念,而是将定义的结构完全当作一个字符串直接处理,不会做任何的处理,也就是静态游标吧。关于dynamic cursor的内容官方有解释http://dev.mysql.com/doc/refman/5.6/en/connector-odbc-usagenotes-functionality.html#connector-odbc-usagenotes-functionality-dynamic-cursor我从5.1找到5.6只有这一个地方讲dynamic cursor而且内容一模一样。

“Support for the dynamic cursor is provided in Connector/ODBC 3.51, but dynamic cursors are not enabled by default. You can enable this function within Windows by selecting the Enable Dynamic Cursor check box within the ODBC Data Source Administrator.On other platforms, you can enable the dynamic cursor by adding 32 to the OPTION value when creating the DSN. ”话说这个意思是使用ODBC的话就可以经过设置之后使用dynamic cursor,关键是我有JDBC,安装程序的时候再自带一个ODBC驱动的话,貌似不太现实,于是考虑其它方式。我总结一下解决这个问题有三种途径。

一、避免使用动态游标的可能性。首先使用所谓动态就是一段代码可复用与多种情况,于是每种情况都写一种代码就可避免,但是作为开发人员,基本没人会这样做。

二、拆分存储过程。假设存在表结构如下:

mysql> desc tree_test;
+———–+————-+——+—–+———+—————-+
| Field       | Type        | Null | Key | Default | Extra          |
+———–+————-+——+—–+———+—————-+
| id             | int(11)     | NO   | PRI | NULL    | auto_increment |
| name      | varchar(11) | NO   |     |              |                |
| parent_id | int(11)     | NO   |         | NULL    |                |
+———–+————-+——+—–+———+—————-+
3 rows in set (0.00 sec)



现在的问题就是将不确定值传给游标,简单的游标定义如下DECLARE cur CURSOR for SELECT * FROM TABLE。这里看到好多人说法是如果在for语句后面使用内置方法方法的话,方法参数可以是你传入的值,也就是说后面的SQL语句是支持方法调用的。没测试,那天测试了再补充吧。就拿后面的 select 语句来说这个语句里面都是确定的值,但是有一个我们可以控制的参数就是表名。表这里可以看作是一个临时的数据集合,如果我们可以控制里面的值,在游标OPEN之后读这个“动态的集合”,于是实现这个有临时表和视图两种途径。在这里我选择视图。现在创建三个PROCEDURE:

CREATE DEFINER=`root`@`localhost` PROCEDURE `proc1`(IN top int)
    BEGIN

    DROP VIEW IF EXISTS tree_test_view;
    SET @sqlstr = "CREATE VIEW tree_test_view as ";
    SET @sqlstr = CONCAT(@sqlstr , "SELECT id FROM tree_test WHERE parent_id = 0 LIMIT ", top);

    PREPARE stmt FROM @sqlstr;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

END

第一个功能很简单,根据条件获得一个ID集合,并把集合存在tree_test_view这个视图中,这里直接在SQL编辑器写的代码,直接运行需要添加存储过程存在判断和DELIMITER转义换行符。现在我们已经获得需要要删除的树的ID集合,因为已只有两级的数,所有只需要知道根的id就可以直接删除整棵树,如果是多级的话就需要进行递归删除,当然前提是需要知道根ID,并且只知道根ID就足够了。
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc2`()
BEGIN

    DECLARE done INT DEFAULT 0;

    DECLARE temp_id INT;
    DECLARE cur CURSOR for( SELECT id from tree_test_view);
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur;
    FETCH cur INTO temp_id;
    WHILE done <> 1 DO
    delete tree_test WHERE id = temp_id or parent_id = temp_id;
    FETCH cur INTO temp_id;
    END WHILE;
    CLOSE cur;
END

这个就是执行的删除操作,基本的游标循环操作,话说这写法好像很有shell和python的韵味。proc1和proc2两个分别执行就可已,当然为了对外的友好,可以再写一个进行统一调用:
REATE DEFINER=`root`@`localhost` PROCEDURE `tree_test_query`(IN top int)

BEGIN

    call proc1(top);
    call proc2();

END



三、第三种是我首先想到的,后来发现原来一般情况下会首先想到第二种,于是我觉得我确实懒的不行了。第三种方法实际就是第二种方法的偷懒方式,把所有的都放在一个存储过程中实现,实际SQL如下:

CREATE DEFINER=`root`@`localhost` PROCEDURE `tree_test_query`(IN top int)
BEGIN

    DECLARE done INT DEFAULT 0;

    DECLARE temp_id INT;
    DECLARE cur CURSOR for( SELECT id from tree_test_view);

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    DROP VIEW IF EXISTS tree_test_view;

    SET @sqlstr = "CREATE VIEW tree_test_view as ";
    SET @sqlstr = CONCAT(@sqlstr , "SELECT id FROM tree_test WHERE parent_id = 0 LIMIT ", top);

    PREPARE stmt FROM @sqlstr;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    OPEN cur;
    FETCH cur INTO temp_id;
    WHILE done <> 1 DO
    DELETE FROM tree_test WHERE id = temp_id or parent_id = temp_id;
    FETCH cur INTO temp_id;
    END WHILE;
    CLOSE cur;
END
分享到:
评论
1 楼 wuyang528378 2015-08-17  
这样的方法的却能解决动态传参的问题,但是在并发访问时会有问题,多个线程操作同一个试图肯定有问题,所以视图的名字也需要动态变化保证不重复,这样一来,试图的名字也是一个变量,问题又回到原点了。

相关推荐

    Mysql游标(循环操作)

    ### MySQL游标(循环操作) #### 一、游标简介 在MySQL中,游标是一种数据库对象,主要用于处理存储过程中的结果集。游标允许我们逐行地读取查询结果,这对于需要对每一行数据执行特定操作的情况非常有用。通过...

    mysql游标

    MySQL游标是数据库管理系统中一个重要的概念,它在处理大量数据时非常有用,尤其是在需要逐行处理查询结果的情况下。游标允许程序动态地访问和操作数据集,而不是一次性加载所有结果。在MySQL中,游标主要用于存储...

    mysql游标详解

    在 MySQL 中,游标的使用和 PL/SQL 有点不同,但基本思想是一样的。游标可以用来实现复杂的数据处理逻辑,例如循环、判断、异常处理等。 在使用游标时,需要注意错误处理。在 MySQL 中,可以使用 CONTINUE HANDLER ...

    mysql游标实现到了最后一个结束之后结束循环

    而“源码”标签可能暗示了博文中会包含一些示例代码来展示如何在应用程序中(可能是使用Java、Python或其他语言)操作MySQL游标。 由于缺少具体博文内容,以上内容是基于对MySQL游标基本概念的解释,若要获取更详细...

    MySql游标的使用实例

    MySQL游标是数据库管理系统中的一个重要概念,主要用于在存储过程或函数中逐行处理查询结果集。游标允许程序按需一次处理一行数据,而非一次性获取所有数据,这在处理大量数据时尤其有用,因为它可以避免一次性加载...

    mysql游标存储过程例子

    根据提供的文件信息,本文将详细解释一个MySQL存储过程的例子,其中包含了游标的使用。这个存储过程主要用于处理一批数据,涉及到日期范围内的数据处理、异常处理等。下面将逐一解析存储过程中涉及的重要知识点。 #...

    mysql游标嵌套[文].pdf

    本文档旨在介绍 MySQL 游标嵌套的概念和实践,通过对游标的嵌套使用,演示如何实现复杂的数据操作。 一、游标嵌套简介 游标(Cursor)是数据库中的一种控制结构,可以用来遍历查询结果集。游标嵌套则是指在一个...

    Mysql中sql语句游标详解

    本文旨在深入探讨MySQL中游标的概念及其使用方法,帮助读者更好地理解和掌握游标在实际开发中的应用。 #### 二、游标概述 ##### 2.1 游标的基本概念 游标是数据库系统中的一个重要概念,它可以理解为一种可以从包含...

    Mysql的游标的定义使用及关闭深入分析

    以上就是MySQL游标的定义、使用和关闭的基本概念以及如何处理游标循环的细节。理解这些概念对于编写涉及复杂数据处理的存储过程至关重要。记住,游标虽然提供了逐行处理数据的能力,但也需要注意性能影响,因为它们...

    MySQL游标概念与用法详解

    MySQL游标是数据库管理系统提供的一种机制,允许程序按需逐行处理查询结果,而不是一次性获取所有数据。在大型数据集处理或需要分步执行复杂逻辑时,游标尤其有用。以下是对MySQL游标概念和用法的详细解释: 1. **...

    mysql游标的原理与用法实例分析

    MySQL游标是数据库管理系统中的一种机制,允许程序逐行处理查询结果集,而不是一次性加载所有数据。这在处理大量数据或者需要逐行处理结果时非常有用。游标提供了向前、向后滚动的能力,使得开发人员可以按需读取、...

    SQL经典游标使用方法

    使用游标时,可以检查`@@FETCH_STATUS`变量判断是否还有更多行可取。如果还有,可以继续使用`FETCH NEXT`,或者使用`WHERE CURRENT OF`更新当前行,甚至执行`DELETE`删除当前行。 4. **关闭和释放游标**: 完成...

    mysql中游标的使用案例详解(学习笔记)

    在MySQL中使用游标涉及到几个关键步骤: **2.1 声明游标** ```sql DECLARE cursor_name CURSOR FOR SELECT statement; ``` 这里`cursor_name`是你给游标起的名字,`SELECT statement`是你想要执行的查询语句。 **...

    mysql动态游标学习(mysql存储过程游标)

    在本示例中,我们将深入探讨如何在MySQL中使用动态游标,特别是结合存储过程来实现这一功能。 首先,创建了一个名为`webuser`的测试表,用于存放用户名数据。接着插入了一些示例数据,包括以'a'和'b'开头的用户。这...

    Oracle存储过程游标详解

    For 循环游标隐式打开游标,自动滚动获取一条记录,并自动创建临时记录类型变量存储记录。处理完后自动关闭游标。While 循环游标需要手动打开和关闭游标,并使用 Fetch 语句获取记录。 在实际应用中,游标可以用于...

    Oracle游标使用方法及语法大全.doc

    3. **读取数据**:使用`FETCH`语句从游标中读取数据行,通常与`INTO`子句结合使用,将数据加载到变量中。 ```sql FETCH c_emp INTO r_emp; ``` 4. **循环读取**:使用循环结构如`LOOP`,结合`EXIT WHEN`条件...

Global site tag (gtag.js) - Google Analytics