游标

===sqlserver cursor:
---语法:
--创建游标:

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. DECLARE cursor_name CURSOR [LOCAL|GLOBAL] [FORWARD_ONLY|SCROLL] [STATIC|KEYSET|DYNAMIC] [READ_ONLY|SCROLL_LOCKS]    
  2. FOR selet_statement [FOR UPDATE[of 列名[,列名]]  
  3. 注:LOCAL 局部游标     GLOBAL 全局游标  
  4.  FORWARD_ONLY 仅向前  SCROLL 滚动  
  5.  STATIC 静态  KEYSET 键集 DYNAMIC 动态  
  6.  READ_ONLY 只读 SCROLL_LOCKS 锁定游标当前行  

--获取游标的数据:

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. FETCH [NEXT|PRIOR|FIRST|LAST|ABSOLUTE{n|@nvar|RELATIVE{n|@nvar}}]  
  2. From cursor_name [into 变量]  
  3. 注:NEXT  下一行  PRIOR  上一行  FIRST 第一行  
  4.  LAST  最后一行  ABSOLUTE n 第n行  
  5.  RELATIVE n 当前位置开始的第n行  
  6.  into 变量 把当前行的各字段值赋值给变量  

--游标状态变量:

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @@fetch_status  游标状态  
  2.      0 成功  -1 失败  -2 丢失  
  3. @@cursor_rows 游标中结果集中的行数  
  4.     n 行数 -1 游标是动态的  0 空集游标  

--操作游标的当前行:
   current of 游标名  
  
--
 (1) 尽管使用游标比较灵活,可以实现对数据集中单行数据的直接操作,但游标会在下面几个方面影响系统的性能:
 --使用游标会导致页锁与表锁的增加
 --导致网络通信量的增加
 -增加了服务器处理相应指令的额外开销
 (2) 使用游标时的优化问题:
 --明确指出游标的用途:for read only或for update
 --在for update后指定被修改的列  
 如果能不用游标,尽量不要使用游标;用完用完之后一定要关闭和释放
 尽量不要在大量数据上定义游标;尽量不要使用游标上更新数据
 尽量不要使用insensitive, static和keyset这些参数定义游标
 如果可以,尽量使用FAST_FORWARD关键字定义游标
 如果只对数据进行读取,当读取时只用到FETCH NEXT选项,则最好使用FORWARD_ONLY参数

  
---sample:  
 游标经常会和全局变量@@FETCH_STATUS与WHILE循环来共同使用,以达到遍历游标所在数据集的目的

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CREATE TABLE t_cursor(id INT,num INT);  
  2. INSERT INTO t_cursor VALUES(1,11),(2,12),(3,13),(4,14),(5,15);  
  3. DECLARE @id INT,@num INT;   
  4. DECLARE c_row CURSOR FOR SELECT id,num FROM t_cursor; --定义游标  
  5. OPEN c_row -- 打开游标  
  6. FETCH NEXT FROM c_row INTO @id,@num; --初始游标数据,放入变量中  
  7. WHILE @@fetch_status=0 --循环判断游标读取状态  
  8. BEGIN  
  9.   SELECT @id as id, @num as num;  
  10.   FETCH NEXT FROM c_row INTO @id,@num; --读取游标下一行  
  11. END  
  12. CLOSE c_row; --关闭游标  
  13. DEALLOCATE c_row; --摧毁游标  




 

===mysql cursor:
http://blog.csdn.net/anialy/article/details/8106370

--语法:
 注意MySQL的游标是向前只读的,也就是说,你只能顺序地从开始往后读取结果集,不能从后往前,也不能直接跳到中间的记录.
 所以读取mysql游标:FETCH cursor_name INTO 变量;  -- 不同于sqlserver的NEXT FROM
 
 mysql不同于sqlserver有@@fetch_status变量,其游标读取结束的标识须另外declare变量进行处理;
 如:DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; --若没有数据返回,程序继续,并将变量done设为true
 或者:DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET n = NULL;
 而且mysql的循环体处理方式也不同于sqlserver,可选择repeat,while,loop三种循环体来读取游标,对应不同的结束处理。

 

--方式1:repeat循环

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CREATE TABLE t_cursor(num INT);  
  2. INSERT INTO t_cursor VALUES(11),(12),(13),(14),(15);  
  3.   
  4. DELIMITER $$  
  5. DROP PROCEDURE IF EXISTS p_curosr$$  
  6. CREATE PROCEDURE p_curosr()  
  7. BEGIN  
  8.     DECLARE n INT;  
  9.     DECLARE done INT DEFAULT 0;  -- 定义int结束标识  
  10.     DECLARE c_row CURSOR FOR SELECT num FROM t_cursor;  
  11.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -- 捕捉异常,设置结束标识  
  12.     OPEN c_row;  
  13.     REPEAT -- repeat循环  
  14.       FETCH c_row INTO n; -- 语法不同于sqlserver,不用先初始fetch next  
  15.       IF NOT done THEN -- 如果没有结束  
  16.          SELECT n;    
  17.       END IF;  
  18.     UNTIL done END REPEAT; -- 结束循环   
  19.     CLOSE c_row;      
  20.     -- DEALLOCATE c_row;  
  21. END$$  
  22. -- 调用  
  23. SELECT * FROM t_cursor;  
  24. CALL p_curosr();  


--方式2:loop循环

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CREATE TABLE t_cursor(num INT);  
  2. INSERT INTO t_cursor VALUES(11),(12),(13),(14),(15);  
  3.   
  4. DELIMITER $$  
  5. DROP PROCEDURE IF EXISTS p_curosr$$  
  6. CREATE PROCEDURE p_curosr()  
  7. BEGIN  
  8.     DECLARE n INT;  
  9.     DECLARE done BOOL DEFAULT FALSE-- 定义bool结束标识  
  10.     DECLARE c_row CURSOR FOR SELECT num FROM t_cursor;  
  11.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE-- 捕捉异常,设置结束标识     
  12.     OPEN c_row;  
  13.     cursorloop: LOOP  -- loop循环     
  14.       FETCH c_row INTO n; -- 语法不同于sqlserver,不用先初始fetch next  
  15.       IF NOT done THEN -- 如果没有结束  
  16.         SELECT n;     
  17.       ELSE   
  18.         LEAVE cursorloop; -- 结束循环       
  19.       END IF;  
  20.     END LOOP cursorloop;    
  21.     CLOSE c_row;      
  22.     -- DEALLOCATE c_row;  
  23. END$$  
  24. -- 调用  
  25. SELECT * FROM t_cursor;  
  26. CALL p_curosr();  


--方式3:while循环

[sql]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CREATE TABLE t_cursor(num INT);  
  2. INSERT INTO t_cursor VALUES(11),(12),(13),(14),(15);  
  3.   
  4. DELIMITER $$  
  5. DROP PROCEDURE IF EXISTS p_curosr$$  
  6. CREATE PROCEDURE p_curosr()  
  7. BEGIN  
  8.     DECLARE n INT;  
  9.     DECLARE c_row CURSOR FOR SELECT num FROM t_cursor;  
  10.     DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET n = NULL;   -- 捕捉异常,设置null   
  11.     OPEN c_row;  
  12.     FETCH c_row INTO n; -- 初始游标  
  13.     WHILE(n IS NOT NULL) DO    -- while循环      
  14.       SELECT n;   
  15.       FETCH c_row INTO n; -- 读取游标  
  16.     END WHILE; -- 结束循环    
  17.     CLOSE c_row;      
  18.     -- DEALLOCATE c_row;  
  19. END$$  
  20. -- 调用  
  21. SELECT * FROM t_cursor;  
  22. CALL p_curosr();  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值