SqlServer和MySQL游标学习

一 sqlserver游标使用

/*** 游标的使用  讲了这个多游标的优点,现在我们就亲自来揭开游标的神秘的面纱。  使用游标的顺序: 声名游标、打开游标、读取数据、关闭游标、删除游标。

1.3.1声明游标 最简单游标声明:DECLARE <游标名>CURSOR FOR<SELECT语句>;

其中select语句可以是简单查询,也可以是复杂的接连查询和嵌套查询 例子:

[已表2 AddSalary为例子] Declare mycursor cursor for select * from AddSalary 这样我就对表AddSalary申明了一个游标mycursor

【高级备注】 DECLARE <游标名> [INSENSITIVE] [SCROLL] CURSORFOR<SELECT语句>

这里我说一下游标中级应用中的[INSENSITIVE]和[SCROLL] INSENSITIVE 表明MS SQL SERVER 会将游标定义所选取出来的数据记录存放在一临时表内(建立在tempdb 数据库下)。

对该游标的读取操作皆由临时表来应答。

因此,对基本表的修改并不影响游标提取的数据,即游标不会随着基本表内容的改变而改变,同时也无法通过游标来更新基本表。如果不使用该保留字,那么对基本表的更新、删除都会反映到游标中。 另外应该指出,当遇到以下情况发生时,游标将自动设定INSENSITIVE 选项。

a.在SELECT 语句中使用DISTINCT、 GROUP BY、 HAVING UNION 语句;

b.使用OUTER JOIN;

c.所选取的任意表没有索引;

d.将实数值当作选取的列。 SCROLL 表明所有的提取操作(如FIRST、 LAST、 PRIOR、 NEXT、 RELATIVE、 ABSOLUTE)都可用。如果不使用该保留字,那么只能进行NEXT 提取操作。由此可见,SCROLL 极大地增加了提取数据的灵活性,可以随意读取结果集中的任一行数据记录,而不必关闭再 重开游标。

1.3.2 打开游标 非常简单,我们就打开刚才我们声明的游标mycursor OPEN mycursor

1.3.3读取数据 FETCH [ NEXT | PRIOR | FIRST | LAST] FROM { 游标名  | @游标变量名 } [ INTO @变量名 [,…] ] 参数说明: NEXT   取下一行的数据,并把下一行作为当前行(递增)。由于打开游标后,行指针是指向该游标第1行之前,所以第一次执行FETCH NEXT操作将取得游标集中的第1行数据。NEXT为默认的游标提取选项。 INTO @变量名[,…]  把提取操作的列数据放到局部变量中。列表中的各个变量从左到右与游标结果集中的相应列相关联。各变量的数据类型必须与相应的结果列的数据类型匹配或是结果列数据类型所支持的隐性转换。变量的数目必须与游标选择列表中的列的数目一致。 现在我们就取出mycursor游标的数据吧! 当游标被打开时,行指针将指向该游标集第1行之前,如果要读取游标集中的第1行数据,必须移动行指针使其指向第1行。就本例而言,可以使用下列操作读取第1行数据:

Eg: Fetch next from mycursor 或则 Fetch first from mycursor 这样我就取出了游标里的数据,但是光光这样可不够,我们还需要将取出的数据赋给变量

--声明2个变量 declare @O_ID NVARCHAR(20)

declare @A_Salary float --将取出的值传入刚才声明的2个变量

Fetch next from mycursor into @ O_ID,@ A_Salary

1.3.4关闭游标 CLOSE mycursor

1.3.5删除游标 DEALLOCATE mycursor

1.3.6 实例训练 **/ CREATE PROCEDURE PK_Test AS

--声明2个变量

declare @O_ID nvarchar(20)

declare @A_Salary float   --声明一个游标mycursor,select语句中参数的个数必须要和从游标取出的变量名相同

declare mycursor cursor for select O_ID,A_Salary from AddSalary

--打开游标

open mycursor

--从游标里取出数据赋值到我们刚才声明的2个变量中

fetch next from mycursor into @O_ID,@A_Salary

--判断游标的状态  -

- 0 fetch语句成功

---1 fetch语句失败或此行不在结果集中

---2 被提取的行不存在

while (@@fetch_status=0)  begin

--显示出我们每次用游标取出的值

print ‘游标成功取出一条数据‘

print @O_ID

print @A_Salary

--用游标去取下一条记录

fetch next from mycursor into @O_ID,@A_Salary  end  -

-关闭游标

close mycursor

--撤销游标

DEALLOCATE mycursor

GO -

---------------------------------------------------------------

create  table  testyoubiao(

id int not null primary key ,

names nvarchar(50),

address nvarchar(50)

)

select top 0 * into testyoubiao2  FROM  testyoubiao

---testyoubiao表中有8条记录

create  PROCEDURE  testpp

as

begin

declare @names nvarchar(20)

declare @address nvarchar(50)

declare mycursor cursor for select names,address from testyoubiao

--打开游标

open mycursor

--从游标里取出数据赋值到我们刚才声明的2个变量中

fetch   next from  mycursor into @names,@address

--while (@@fetch_status=0)

--begin

--显示出我们每次用游标取出的值

print ‘1‘

print @names

print @address

--用游标去取下一条记录

--  fetch  mycursor into @names,@address

insert into testyoubiao2(names,address) values(@names,@address)

--end

--关闭游标

close mycursor

--撤销游标

DEALLOCATE mycursor end

exec testpp

--这样执行的结果testyoubiao2表只有一条记录 就是说没有循环就是只去第一条

--fetch   next from  mycursor into @names,@address  "next from"这个可以不写结果是一样的

--------------------------------------------------------------------

create  PROCEDURE  testpp

as begin

declare @names nvarchar(20)

declare @address nvarchar(50)

declare mycursor cursor for select names,address from testyoubiao

--打开游标

open mycursor

--从游标里取出数据赋值到我们刚才声明的2个变量中

fetch  next  from   mycursor into @names,@address

-- insert into testyoubiao2(names,address) values(@names,@address) 会增加一条数据与最后一条相同

while (@@fetch_status=0)

begin

--显示出我们每次用游标取出的值

print ‘1‘

print @names

print @address

--用游标去取下一条记录

fetch next  from  mycursor into @names,@address

insert into testyoubiao2(names,address) values(@names,@address)

end

--关闭游标

close mycursor

--撤销游标

DEALLOCATE mycursor end

exec testpp

select * from testyoubiao2

truncate  table    testyoubiao2

drop  PROCEDURE  testpp

#----------------------------------------------------------------------

二 MySQL游标使用

DELIMITER $$

create PROCEDURE testp16(in $id int )

BEGIN declare  _uname varchar(20) ;

declare _uaddress VARCHAR(20);

DECLARE D_cursor CURSOR FOR select uname,uaddress from testa where id=$id;

OPEN D_cursor; FETCH NEXT FROM D_cursor  into  _uname, _uaddress;

CLOSE D_cursor;

insert into testd(uname,uaddress)values(_uname,_uaddress);

end;

-----------------------------------------------------------

DELIMITER $$

create PROCEDURE testp17()

BEGIN  declare  _uname varchar(20) ;

declare _uaddress VARCHAR(20);

declare couts int ;

declare i int default 0 ;

DECLARE D_cursor CURSOR FOR select uname,uaddress from testa;

set couts =(select count(id)from testa);

OPEN D_cursor;

-- FETCH NEXT FROM D_cursor  into  _uname, _uaddress;

-- insert into testd(uname,uaddress)values(_uname,_uaddress);这个地方加上这两句数据时对的但是会有1329 错误提示

while i<couts DO -- 1329 - No data - zero rows fetched, selected, or processed 超出范围了

FETCH NEXT FROM D_cursor  into  _uname, _uaddress;

insert into testd(uname,uaddress)values(_uname,_uaddress);

set i=1+i;

end while;

-- FETCH NEXT FROM D_cursor  into  _uname, _uaddress;

-- insert into testd(uname,uaddress)values(_uname,_uaddress);这个地方加上这两句数据时对的但是会有1329 错误提示 CLOSE D_cursor; select i; end;

select * from testa

CALL testp17();--1329 - No data - zero rows fetched, selected, or processed 超出范围了

CALL testp18()

select * from testd

TRUNCATE table testd

-----------------------------------------

/*为下面的理解说明 定义条件和处理程序 定义条件和处理程序是事先定义程序执行过程中可能遇到的问题。并且可以在处理程序中定义解决这些问题的办法。这种方式可以提前预测可能出现的问题,并提出解决办法。这样可以增强程序处理问题的能力,避免程序异常停止。MySQL中都是通过DECLARE关键字来定义条件和处理程序。

本小节中将详细讲解如何定义条件和处理程序。

1.定义条件 MySQL中可以使用DECLARE关键字来定义条件。

其基本语法如下:

DECLARE  condition_name  CONDITION  FOR  condition_value  condition_value:

SQLSTATE [VALUE] sqlstate_value | mysql_error_code

其中,condition_name参数表示条件的名称;

condition_value参数表示条件的类型;sqlstate_value参数和mysql_error_code参数都可以表示MySQL的错误。

例如ERROR 1146 (42S02)中,sqlstate_value值是42S02,mysql_error_code值是1146。

【示例14-6】

下面定义"ERROR 1146 (42S02)"这个错误,名称为can_not_find。可以用两种不同的方法来定义,代码如下:

//方法一:使用sqlstate_value  DECLARE  can_not_find  CONDITION  FOR  SQLSTATE  ‘42S02‘ ;

//方法二:使用mysql_error_code  DECLARE  can_not_find  CONDITION  FOR  1146 ; 2.定义处理程序

MySQL中可以使用DECLARE关键字来定义处理程序。

其基本语法如下: DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement  handler_type:

CONTINUE | EXIT | UNDO  condition_value:

SQLSTATE [VALUE] sqlstate_value | condition_name  | SQLWARNING         | NOT FOUND  | SQLEXCEPTION  | mysql_error_code

其中,handler_type参数指明错误的处理方式,该参数有3个取值。这3个取值分别是CONTINUE、EXIT和UNDO。CONTINUE表示遇到错误不进行处理,继续向下执行;

EXIT表示遇到错误后马上退出;UNDO表示遇到错误后撤回之前的操作,MySQL中暂时还不支持这种处理方式。

注意:通常情况下,执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。

但是,MySQL中现在还不能支持UNDO操作。因此,遇到错误时最好执行EXIT操作。如果事先能够预测错误类型,并且进行相应的处理,那么可以执行CONTINUE操作。 condition_value参数指明错误类型,该参数有6个取值。sqlstate_value和mysql_error_code与条件定义中的是同一个意思。condition_name是DECLARE定义的条件名称。SQLWARNING表示所有以01开头的sqlstate_value值。NOT FOUND表示所有以02开头的sqlstate_value值。SQLEXCEPTION表示所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值。sp_statement表示一些存储过程或函数的执行语句。

【示例14-7】 下面是定义处理程序的几种方式。

代码如下:

//方法一:捕获sqlstate_value  DECLARE CONTINUE HANDLER FOR SQLSTATE ‘42S02‘ SET @info=‘CAN NOT FIND‘;

//方法二:捕获mysql_error_code  DECLARE CONTINUE HANDLER FOR 1146 SET @info=‘CAN NOT FIND‘;

//方法三:先定义条件,然后调用  DECLARE  can_not_find  CONDITION  FOR  1146 ;

DECLARE CONTINUE HANDLER FOR can_not_find SET @info=‘CAN NOT FIND‘;

//方法四:使用SQLWARNING  DECLARE EXIT HANDLER FOR SQLWARNING SET @info=‘ERROR‘;

//方法五:使用NOT FOUND  DECLARE EXIT HANDLER FOR NOT FOUND SET @info=‘CAN NOT FIND‘;

//方法六:使用SQLEXCEPTION  DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info=‘ERROR‘;

上述代码是6种定义处理程序的方法。

第一种方法是捕获sqlstate_value值。如果遇到sqlstate_value值为42S02,执行CONTINUE操作,并且输出"CAN NOT FIND"信息。

第二种方法是捕获mysql_error_code值。如果遇到mysql_error_code值为1146,执行CONTINUE操作,并且输出"CAN NOT FIND"信息。

第三种方法是先定义条件,然后再调用条件。这里先定义can_not_find条件,遇到1146错误就执行CONTINUE操作。

第四种方法是使用SQLWARNING。SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT操作,并且输出"ERROR"信息。

第五种方法是使用NOT FOUND。NOT FOUND捕获所有以02开头的sqlstate_value值,然后执行EXIT操作,并且输出"CAN NOT FIND"信息。

第六种方法是使用SQLEXCEPTION。SQLEXCEPTION捕获所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值,然后执行EXIT操作,并且输出"ERROR"信息。

*/ -----------------------------------

DELIMITER $$

CREATE PROCEDURE testp18()

BEGIN

-- 遍历数据结束标志

DECLARE done INT DEFAULT FALSE;

-- 需要定义接收游标数据的变量

declare  _uname varchar(20) ;

declare _uaddress VARCHAR(20);

-- 游标

DECLARE D_cursor CURSOR FOR select uname,uaddress from testa;

/* 遍历数据结束标志

--DECLARE done INT DEFAULT FALSE;

-- #放到这里出现这个错误[Err] 1337 - Variable or condition declaration after cursor or handler declaration   根据错误的提示信息,游标定义需在变量/条件后,HANDLER 前。   */

-- 将结束标志绑定到游标

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- 打开游标

OPEN D_cursor;

--FETCH  D_cursor INTO _uname, _uaddress;

--insert into testd(uname,uaddress)values(_uname,_uaddress); 这里多加这两句不影响后面的数据

-- 开始循环

read_loop: LOOP

-- 提取游标里的数据,这里只有一个,多个的话也一样;

FETCH next from  D_cursor INTO _uname, _uaddress;-- next from可以省略

-- 声明结束的时候

IF done THEN

LEAVE read_loop;

END IF;

-- 这里做你想做的循环的事件

insert into testd(uname,uaddress)values(_uname,_uaddress);

END LOOP;

-- FETCH  D_cursor INTO _uname, _uaddress;这里如果加上这两句会增加一条数据与最后的数据相同

--insert into testd(uname,uaddress)values(_uname,_uaddress);

-- 关闭游标

CLOSE D_cursor;

END

-- testp17()和testp18()两个效果是一样的 -

----------------------------------------

SqlServer和MySQL游标学习

时间: 2024-10-12 18:40:11

SqlServer和MySQL游标学习的相关文章

MYSQL 游标学习及使用实例

who?(游标是什么?)游标(cursor)官方定义:是系统为用户开通的一个数据缓冲区,存放sql执行结果.每个游标区都有一个名字,用户可以通过sql语句逐一从游标中获取记录,并赋值给变量,交由主语言进一步处理;个人理解:感觉游标和指针相似,指定结果集后一行行执行; why?(为什么要学习游标)游标允许应用程序对查询语句select 返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作:它还提供对基于游标位置而对表中数据进行删除或更新的能力:而且,正是游标把作为面向集

MYSQL进阶学习知识拓展一:MySQL 存储过程之游标!

一.MySQL游标的概念 游标介绍: MySQL的游标(cursor)是一个重要的概念,通过查找资料与自己的理解,主要得出以下几点关于自己的理解. 有数据缓冲的思想:游标的设计是一种数据缓冲区的思想,用来存放SQL语句执行的结果. 先有数据基础:游标是在先从数据表中检索出数据之后才能继续灵活操作的技术.   类似于指针:游标类似于指向数据结构堆栈中的指针,用来pop出所指向的数据,并且只能每次取一个. 游标优缺点: 游标的优点: 因为游标是针对行操作的,所以对从数据库中select查询得到的每一

SqlServer 与 MySQL 基本操作语句对比

继上篇 MySQL 基本操作语句 后,个人测试和补充了 SqlServer 与 MySQL 的 基本操作语句对比,主要是对比SQL命令的一些差异,不作更多说明. (由于mysql 没有系统学习过,欢迎大侠们拍砖~~)  SqlServer版本:SqlServer 2008 MySQL版本: MySQL 5.5 执行符号: MySQL :分号';' SqlServer :字符'GO' 自增列:MySQL必须要索引,不能设置增量: 默认值:MySQL默认值不用加括号:SqlServer可加或不加:

你搞懂 ORACLE、 SQLSERVER、MYSQL与DB2的区别了吗

ORACLE. SQLSERVER.MYSQL与DB2的区别--平台性:    Oracle.MYSQL与DB2可在所有主流平台上运行:    SQL Server只能在Windows下运行: --安全性:    Oracle的安全认证获得最高认证级别的ISO标准认证,而SQL Server并没有获得什么安全认证:    这方面证明了Oracle的安全性是高于SQL Server的: --数据类型.函数.sql语句:    oracle中有复合数据类型,sql server中没有: 总之:   

MYSQL数据库学习笔记1

MYSQL数据库学习笔记1 数据库概念 关系数据库 常见数据库软件 SQL SQL的概念 SQL语言分类 数据库操作 创建数据库 查看数据库的定义 删除数据库 修改数据库 创建表 数据类型 约束 修改表 表的增删查改 查询 数据库概念 数据库是一种对大量信息进行管理的一种方法. 数据库系统从结构上看,也是可以分为三层的: 物理层:数据实际如何存储 逻辑层:存储的是什么数据,以及数据间是什么关系 试图层:提供给用户的部分数据 关系数据库 目前关于数据库模型最主流的有两种, 一种叫做关系型数据库,这

MySQL数据库学习初步

我使用的环境是Win7,开始学习PHP和MySQL,并且买了本<Head First PHP & MySQL>,可以从Head First Labs官网获得HeadFirst系列书籍的相关信息和源代码. 1.下载XAMPP开发包 从XAMPP中文官网下载目前比较流行的PHP开发包,XAMPP是完全免费且易于安装的Apache发行版,其中包含MySQL.PHP和Perl.XAMPP适用于Windows.Mac OS X和Linux,XAMPP开放源码包的设置让安装和使用出奇容易.我下载的

[转]MySQL游标的使用

转自:http://www.cnblogs.com/sk-net/archive/2011/09/07/2170224.html 以下的文章主要介绍的是MySQL游标的使用笔记,其可以用在存储过程的SQL语句,其主要类型主要有以下几种,以下就是对其详细介绍,相信如果你掌握了这项技术,会在以后的学习或是工作中带来很大的帮助. 1. 无返回结果语句,如:INSERT,UPDATE,DROP, DELETE等 2. select语句返回单行变量并可传给本地变量(select ..into) 3. 返回

mysql触发器学习

创建一个触发器 语法: create trigger 触发器名字 create trigger xiaoshou_update_trigger  after update on xiaoshou  for each row  begin  update jiangjin  set xiaoshouer=( select sum(taoshu*danjia)from xiaoshou  where userid=new.userid  and month=new.month) , jiangjin

MySQl Study学习之--MySQl二进制日志管理

MySQl Study学习之--MySQl二进制日志管理 MySQL二进制日志(Binary Log):   a.它包含的内容及作用如下:    包含了所有更新了数据或者已经潜在更新了数据(比如没有匹配任何行的一个DELETE)    包含关于每个更新数据库(DML)的语句的执行时间信息    不包含没有修改任何数据的语句,如果需要启用该选项,需要开启通用日志功能    主要目的是尽可能的将数据库恢复到数据库故障点,因为二进制日志包含备份后进行的所有更新    用于在主复制服务器上记录所有将发送