SQL之游标

要在程序设计中使用游标,必须先声明,声明方式和声明变量一样。
必须使用4个SQL语句才能完成发挥游标的功能:
①declare cursor 通过定义游标名称,游标特征来声明游标,以及打开游标后就可用来调用的查询表达式
②open打开游标并调用查询表达式,生成可被fetvh语句使用的查询结果
③fetch把数据赋给变量,并通过变量把数据传递给程序设计语言或其他的嵌入式SQL语句
④close关闭游标。一旦关闭游标,就不能再从查询结果中检索数据了声明游标:
declare cursor语句,在使用游标检索数据之前必须先声明游标。可以在程序代码的任何位置声明游标,只要在其他语句中使用游标语句之前声明就可以了。
游标声明的语法有很多组成部分:
declare
[sensitive | insensitive|asensitive]
[scroll | not scroll] cursor
[with hold| without hold]
[with return|without return]
for
[order by ]
[for {read cnly|update[of ]}]可以看出,大部分组成都是可选项。
基本语法形式:
declare cursor for
这个语法只心事必选的游标声明部分可选的语法组成:
1:游标灵敏性
[sensitive | insensitive | asensitive]
游标灵敏性和游标以外但影响游标返回的行语句有关
sensitive:游标以外的语句所做的显著改变立即影响游标的查询结果
insensitive:游标以外的语句所做的显著该表不影响游标的查询结果
asensitive:游标的灵敏性是由工具定义的,显著该表在游标内部未必可见
如果没有指定游标灵敏性,默认选项是asensitive。2:游标滚动性:
[scroll| no scroll]
滚动性是与fetch语句和它用来检索数据的选项直接相关的。
如果指定scroll选项,fetch被可选项定义,定义这些可选项遍历查询结果并返回特定的行,scroll选项允许fetch语句根据需要跳过查询结果检索到特定的行。
如果在游标声明是指定no scroll,fetch语句不能利用附加滚动选项并且只能检索到查询结果中的下一行。
如果没有指定选项,no scroll为默认设置3:游标持久性
[with hold | without hold]
游标持久性指的是当食物提交后,事物中的已被开启的游标是否自动关闭。
一个事物就是一个单元,就是说事物中的所有语句一旦被使用,必须全部完成。执行事物中的一些语句后,只要一个语句发生失败,所有已执行语句就被撤销,数据库保持不变
如果是with hold ,在提交事物后游标仍然打开,直到显示关闭事物为止。
如果是without hold,提交事物后自动关闭游标。
如果两项都没有选,默认是without,事物提交后游标自动关闭4:游标返回性
[with return | without return]
如果用with return,游标被认为是结果集游标。在、如果咋SQL调用过程中打开了游标,就把游标的结果集返回给过程调用器
如果是without return,不管在SQL调用过程中是否打开游标,都正常返回游标结果集。
如果啷个选项都没指定,默认是without return5:游标排序
[order by]
如果使用order by子句,游标的select语句就不能有group by子句和having子句。另外select子句中也不能指定distinct关键字或使用集合函数6:游标的更新性
[for {read only | update | of}]
游标更新性指游标能否用update或delete语句修改游标的select语句返回的数据
read only项,如果用read only,就不能对游标的select语句返回的数据执行update和delete语句。
如果用update,就能执行这些语句
如果两项都没指定,默认为update
注意:可用update选项指定表中可被更新的列,要更新列,必有of关键字,其后是一个或多个列名。如果不知一列,列明之间用逗号隔开。
如果没有任何列名(和of关键字),update选项应用于表中所有的列
-----------------------------------------------------------------
第一个示例是只有必选项和order by子句的基本游标声明。
declare CD1 cursor
for
select * from CDInventory
order by compactdisc第二个示例定义滚动查询
declare CD2 scroll cursor
for
select * from CDInventory
order by compactdisc
for read only
注意:此语句中增加了两个组成部分:scroll关键字和for read only子句。
scroll关键字通知fetch语句游标可以滚动。结果,在fetch语句中就可使用附加选项让应用程序遍历游标结果。第三个示例定义可更新游标
declare CD4 cursor
for
select * from CDInventory
for update
注意这个declare cursor语句没有scroll关键字,insensitive关键字和order by子句,这些都不能创建可更新游标。第四个示例只想让游标对于某一列是可更新的declare CD5 cursor
for
select * from CDInventory
for update of compactdisc;
现在for update子句中有关键字of和列名compactdisc。如果要修改游标返回的结果中有其他列的数据,就会出错
打开和关闭游标
打开游标的过程非常简单,只需要关键字open和游标的名字就行
open
必须声明游标后才能打开,声明后就可以在程序的任何位置打开,也只有在打开游标后才能调用游标中的select语句。就是说在声明游标这段时间内修改的数据都能反映在游戏的返回结果中,如果关闭再打开游标,这段时间内的数据改变会反映在新的数据查询结果中。
close
关闭游标后就不能再检索查询结果中的行
检索游标返回的数据
打开右边后执行一个或多个fetch语句。每个语句都指定查询结果中的一行,然后从这些行中提取值。
fetch语法:
fetch[[] from]
into
从语法中可以看出,必须指定fetch关键字和游标的名字,还有一个into子句用来确定接受fetch语句返回值的主变量。
如果fetch语句中有多个主变量,每个变量之间用逗号隔开。
fetch语句中除了必选项外,还有可选项占位符和from关键字。
next 检查查询结果中的下一行。如果在打开游标后第一个fetch语句中使用next,将会返回查询结果中的第一行。第二个fetch next 语句会返回查询结果中的第2行
prior检索上一个检索到的行的上一行。如果在打开游标后的第一个fetch语句中使用,没有返回行,因为第一行上面没有行
first无论在打开游标后执行了多少fetch语句,检索游标查询结果中的第一行
last无论在打开游标后执行了多少fetch语句,检索游标查询结果的最后一行
absolute检索占位符指定的行。这个值必须是一个确切的数字,尽管它可以从主变量中得到。这个数字指明fetch语句返回哪一行 例如:absolute 1 返回第一行,absolute 2返回第二行,absolute-1返回最后一行
relative检索相对于当前游标位置的行,相对位置有占位符指定,如果在打开游标后第一个fetch语句中使用,relative 1 返回查询结果中的第一行,relative-1返回查询结果中的最后一行。但是如果游标不位于查询结果的开始,如第一次打开游标,relative 1 和 relative -1 返回相对于上一次执行fetch语句的游标位置的行使用定位update语句
定位update语句除了需要特殊的where子句外,其他都和正常的update语句一样:
语法:
update
set
where current of 实例:声明一个名为CD4的游标,打开该游标后从他的查询结果中提取一行,更新这一行数据,最后再关闭游标
declare CD4 cursor
for
select * from CDInventory
for update;
open CD4;
fetch CD4 into :cd,:category,:price,:onhand;
update CDInventory set onhand=:onhand*2
where current of CD4;
close CD4;实例:定义一个显式定义列declare CD5 cursor
for
select * from CDInventory
for update of compactdisc;
open CD5;
fetch CD5 into :CD,:category,:price,:onhand;
update CDInventory set onhand=:onhand*2
where current of CD5;
close CD5;注意这个语句执行的结果是错的,因为在for update of 已经指明了需要更新的列
如果在update执行语句的列不等于for update of列是报错的使用定位delete语句定位delete语句的语法:
delete
where current of 实例:删除一行
declare CD 6 cursor
for
select * CDInventory
for update;
open CD6;
fetch CD6 into :cd,:category;:price,:onhand;
delete CDInventory where current of CD6;
close CD6;项目:--创建触发器
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[TRG_ZC_ZCINFO_JG_INS]'))
DROP TRIGGER [dbo].[TRG_ZC_ZCINFO_JG_INS]
GO
-- =============================================
-- Author:
-- Create date:
-- Description:
-- =============================================
CREATE TRIGGER [TRG_ZC_ZCINFO_JG_INS]
ON [dbo].[ZC_ZCINFO_JG]
AFTER INSERT
AS
BEGIN
DECLARE @DJBH VARCHAR(20) --单据编号
DECLARE @YWLX VARCHAR(2) --业务类型
DECLARE @XMBH VARCHAR(12) --项目编号
DECLARE @PZH VARCHAR(20) --财务凭证号
DECLARE @CWRZRQ VARCHAR(10) --财务入账日期
DECLARE @CWZDZT VARCHAR(2) --财务制单状态 0:退回 1:制单成功
DECLARE @CWSHR VARCHAR(20) --财务审核人
DECLARE @CWSM VARCHAR(255) --财务审核说明
DECLARE @CWSH_TG VARCHAR(20)--财务审核通过 99
DECLARE @CWSH_TH VARCHAR(20)--财务审核退回 91
DECLARE @CWSHR_RYBH VARCHAR(20)--财务人员 SET @CWSH_TG='99'
SET @CWSH_TH='91'
--声明游标
DECLARE INSERT_CURSOR SCROLL CURSOR FOR
SELECT DJBH,YWLX,XMBH,PZH,CWRZRQ,CWZDZT,CWSHR,CWSM FROM INSERTED ORDER BY DJBH
--打开游标
OPEN INSERT_CURSOR
FETCH NEXT FROM INSERT_CURSOR INTO @DJBH,@YWLX,@XMBH,@PZH,@CWRZRQ,@CWZDZT,@CWSHR,@CWSM WHILE @@FETCH_STATUS=0
BEGIN
--获取财务审核人员RYBH
SELECT TOP 1 @CWSHR_RYBH=RYBH FROM RYB WHERE LTRIM(RTRIM(XM))=LTRIM(RTRIM(@CWSHR))
IF @YWLX='1' --验收单增加
BEGIN
IF @CWZDZT='1'
BEGIN
UPDATE YSHD SET ZTBZ=@CWSH_TG,SHRQ=GETDATE(),SHYJ=@CWSM,CWRY=@CWSHR_RYBH,PZH=@PZH,JZRQ=@CWRZRQ,XMH=@XMBH WHERE YSHDH=@DJBH
UPDATE ZJB SET ZTBZ=@CWSH_TG,SHRQ=GETDATE(),SHYJ=@CWSM,SHR=@CWSHR_RYBH,PZH=@PZH,RZRQ=@CWRZRQ,DZRRQ=@CWRZRQ,XMH=@XMBH WHERE YSDH=@DJBH
UPDATE YSHDFJ SET ZTBZ=@CWSH_TG WHERE YSHDH=@DJBH
END
ELSE
BEGIN
UPDATE YSHD SET ZTBZ=@CWSH_TH,SHRQ=GETDATE(),SHYJ=@CWSM,CWRY=@CWSHR_RYBH,XMH=@XMBH WHERE YSHDH=@DJBH
UPDATE ZJB SET ZTBZ=@CWSH_TH,SHRQ=GETDATE(),SHYJ=@CWSM,SHR=@CWSHR_RYBH,XMH=@XMBH WHERE YSDH=@DJBH
UPDATE YSHDFJ SET ZTBZ=@CWSH_TH WHERE YSHDH=@DJBH
END
END
ELSE IF @YWLX='2' --资产价值变动
BEGIN
IF @CWZDZT='1'
BEGIN
UPDATE BDBGB SET ZTBZ=@CWSH_TG,SHRQ=GETDATE(),SHNR=@CWSM,SHR=@CWSHR_RYBH,PZH=@PZH,JZRQ=@CWRZRQ WHERE BDBGBH=@DJBH
UPDATE ZJB SET BDZT=0 FROM ZJB,BDB,BDBGB WHERE ZJB.YQBH=BDB.FJBH AND BDB.BDBGBH=BDBGB.BDBGBH AND BDBGB.BDBGBH=@DJBH AND BDB.BZ='1'
END
ELSE
BEGIN
UPDATE BDBGB SET ZTBZ=@CWSH_TH,SHRQ=GETDATE(),SHNR=@CWSM,SHR=@CWSHR_RYBH WHERE BDBGBH=@DJBH
END
END
ELSE IF @YWLX='3' --资产处置
BEGIN
IF @CWZDZT='1'
BEGIN
UPDATE CZBGB SET ZTBZ=@CWSH_TG,SHRQ=GETDATE(),SHNR=@CWSM,SHR=@CWSHR_RYBH,PZH=@PZH,JZRQ=@CWRZRQ WHERE BDBGBH=@DJBH
UPDATE CZB SET BDBZ=@CWSH_TG WHERE BDBGBH=@DJBH
END
ELSE
BEGIN
UPDATE CZBGB SET ZTBZ=@CWSH_TH,SHRQ=GETDATE(),SHNR=@CWSM,SHR=@CWSHR_RYBH WHERE BDBGBH=@DJBH
UPDATE CZB SET BDBZ=@CWSH_TH WHERE BDBGBH=@DJBH
END
END
FETCH NEXT FROM INSERT_CURSOR INTO @DJBH,@YWLX,@XMBH,@PZH,@CWRZRQ,@CWZDZT,@CWSHR,@CWSM
END
--关闭游标
CLOSE INSERT_CURSOR
DEALLOCATE INSERT_CURSOR
END 

相关内容推荐