sql server 存储过程使用游标记录--方便下次参考使用
游标的组成:
- 声明游标
- 打卡游标
- 从一个游标中查找信息
- 关闭游标
- 释放游标
游标类型:
- 静态游标
- 动态游标
- 只进游标
- 键集驱动游标
静态游标:静态游标的完整结果集在游标打开时建立在tempdb中。静态游标总是按照游标打开时的原样显示结果集。
静态游标在滚动期间很少或根本监测不到变化,虽然在tempdb中存储了整个游标,但消耗的资源很少。尽管动态游标使用tempdb的程度最低,在滚动期间它能够监测到所有变化,单消耗的资源也更多。
键集驱动游标介于二者之间,它能够监测到大部分的变化,但比动态游标消耗更少的资源。
动态游标:与静态游标相对。当滚动游标时,动态游标反映结果集中所作的所有更改。结果集中的行数据值、顺序和成员在每次提取时都会改变。所有用户做的全部update、insert、delete语句均通过游标可见。
只进游标:只进游标不支持滚动,它只支持游标从头到尾顺序提取。只在从数据库中提取出来后才能进行检索。对所有由当前用户发出或其他用户提交,并影响结果集中的行的insert、update、delete语句,其效果在这些行从游标中提取时是可见的。
键集驱动游标:打开游标时,键集驱动游标中的成员和行顺序是固定的。键集驱动游标由一套被称为键集的唯一标识符(键)控制。键由以唯一方式在结果集中标识行的列构成。键集是游标打开时来自所有适合select语句的行中的一系列键值,键集驱动
游标打开时建立在tempdb中。对非键集列中的数据值所做的更改(由游标所有者更改或其他用户提交)在用户滚动游标时是可见的,在游标外对数据库所做的插入在游标内是不可见的,除非关闭并重新打开游标。
参考实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | USE [hhris] GO /****** Object: StoredProcedure [dbo].[INIT_DICT_QUEUECODE] Script Date : 2018-09-21 17:12:12 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO --if (exists (select * from sys.objects where name = 'INIT_DICT_QUEUECODE')) --drop proc INIT_DICT_QUEUECODE --go --create procedure INIT_DICT_QUEUECODE -- ============================================= -- Author: <sunwugang> -- ALTER date: <2018-09-21> -- Description: <添加参数维护> -- ============================================= ALTER procedure [dbo].[INIT_DICT_QUEUECODE] ( @p_QUEUEID int , @p_QUEUENAME varchar (100), @p_DEVICECOUNT int , @p_CHECKDURATION int , @p_BEGINTIMEPART varchar (50), @p_ENDTIMEPART varchar (50), @p_CODECOUNT int , @p_QUEUESIGN varchar (50), @p_ADDRESS varchar (50), @p_ofdepart varchar (30), @p_PMBEGINTIME varchar (50), @p_PMENDTIME varchar (50), @p_CodeCoefficient varchar (50), @p_TIMEPART varchar (50), @p_PARAMTYPE varchar (50), @p_CALLTYPE varchar (50), @p_result int output ) as insert into QS_PARAM (QUEUEID, QUEUENAME, DEVICECOUNT, CHECKDURATION, BEGINTIMEPART, ENDTIMEPART, CODECOUNT,QUEUESIGN,ADDRESS,ofdepart,PMBEGINTIME, PMENDTIME, CodeCoefficient, TIMEPART,PARAMTYPE,CALLTYPE) values (@p_QUEUEID, @p_QUEUENAME, @p_DEVICECOUNT, @p_CHECKDURATION, @p_BEGINTIMEPART, @p_ENDTIMEPART, @p_CODECOUNT,@p_QUEUESIGN,@p_ADDRESS,@p_ofdepart,@p_PMBEGINTIME, @p_PMENDTIME, @p_CodeCoefficient, @p_TIMEPART,@p_PARAMTYPE,@p_CALLTYPE) declare @loopNum int , --循环次数 @codeNum int , --号源编号 @codeFirstAm int , @codeFirstPm int DECLARE paramDetails cursor for select queuename,paramtype,begintimepart,endtimepart,ofdepart,calltype,codecount from qs_param a where a.queueid=@p_QUEUEID and a.paramtype=@p_PARAMTYPE order by convert ( float ,endtimepart) begin try set @loopNum=1 set @codeNum=1 set @codeFirstAm=0 --未进行初始化 set @codeFirstPm=0 --未进行初始化 --删除号源字典 delete from dict_queuecode where queuename=@p_QUEUENAME and codeparamtype=@p_PARAMTYPE and ofdepart=@p_ofdepart begin tran --当前事务点,rollback、commit都从这里开始 DECLARE @v_QUEUEID int , @v_QUEUENAME varchar (100), @v_DEVICECOUNT int , @v_CHECKDURATION int , @v_BEGINTIMEPART varchar (50), @v_ENDTIMEPART varchar (50), @v_CODECOUNT int , @v_QUEUESIGN varchar (50), @v_ADDRESS varchar (50), @v_ofdepart varchar (30), @v_PMBEGINTIME varchar (50), @v_PMENDTIME varchar (50), @v_CodeCoefficient varchar (50), @v_TIMEPART varchar (50), @v_PARAMTYPE varchar (50), @v_CALLTYPE varchar (50) open paramDetails fetch next from paramDetails into @v_queuename,@v_paramtype,@v_begintimepart,@v_endtimepart,@v_ofdepart,@v_calltype,@v_codecount WHILE @@FETCH_STATUS =0 begin --循环获取qs_param表中维护的某个时间段 set @loopNum=1 while @loopNum <= @v_codecount begin --上午 if @codeFirstAm=0 and @v_calltype= '上午' begin set @codeNum=1 set @codeFirstAm=1 end --下午 if @codeFirstPm=0 and @v_calltype= '下午' begin set @codeNum=1 set @codeFirstPm=1 end --添加号源信息 insert into DICT_QUEUECODE (queuename,codeparamtype,codevalue,timepart,hintinfo,OFDEPART,calltype,queueid) values (@v_queuename,@v_paramtype,@codeNum,@v_begintimepart+ '~' +@v_endtimepart, '' ,@v_ofdepart,@v_calltype,@p_QUEUEID) --重新赋值 set @loopNum=@loopNum+1 set @codeNum=@codeNum+1 end fetch next from paramDetails into @v_queuename,@v_paramtype,@v_begintimepart,@v_endtimepart,@v_ofdepart,@v_calltype,@v_codecount end close paramDetails DEALLOCATE paramDetails set @p_result=1 commit end try begin catch set @p_result=-1 rollback end catch |
实例二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | USE [MES30] GO /****** Object: StoredProcedure [dbo].[sp_WM_DeliveryCommit] Script Date : 2018/9/20 16:21:13 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: -- ALTER date: <2017-06-13> -- Description: <发货单提交> -- ============================================= ALTER procedure [dbo].[sp_WM_DeliveryCommit] ( @DeliveryCode NVARCHAR(50) ) AS BEGIN SET NOCOUNT ON ; DECLARE @ERROR_MESSAGE NVARCHAR(4000); DECLARE @Flag NVARCHAR(50) SET @Flag= '0' ; BEGIN TRY BEGIN TRAN; DECLARE DeliveryCursor CURSOR FOR SELECT MatCode,DeliveryQty FROM t_WM_DeliveryDtl WHERE _DeliveryCode=@DeliveryCode OPEN DeliveryCursor DECLARE @MatCode nvarchar(50),@DeliveryQty decimal (22,6) FETCH NEXT FROM DeliveryCursor INTO @MatCode,@DeliveryQty WHILE @@FETCH_STATUS =0 BEGIN DECLARE @tmpDeliveryQty decimal (22,6),@tmpRequireQty decimal (22,6),@tmpReturnQty decimal (22,6) DECLARE @tmpStockQty decimal (22,6),@tmpQty decimal (22,6) SELECT @tmpDeliveryQty= SUM ( isnull (DeliveryQty,0)) FROM t_WM_DeliveryDtl,t_WM_Delivery WHERE DeliveryCode=_DeliveryCode and (DeliverySts=2 OR DeliverySts=3) and MatCode=@MatCode SELECT @tmpRequireQty= SUM ( isnull (RequireQty,0)) FROM t_WM_RequireDtl,t_WM_Require WHERE RequireCode=_RequireCode and (RequireSts=2 OR RequireSts=3) and MatCode=@MatCode SELECT @tmpRequireQty= SUM ( isnull (ReOutQty,0)) FROM t_WM_ReturnOutDtl,t_WM_ReturnOut WHERE ReOutCode=_ReOutCode and (ReOutSts=2 OR ReOutSts=3) and MatCode=@MatCode SELECT @tmpStockQty= SUM ( isnull (ValidQty,0)) FROM t_WM_InDtl,t_WM_In WHERE InCode=_InCode and MatCode=@MatCode SET @tmpQty= isnull (@tmpStockQty,0)- isnull (@tmpDeliveryQty,0)- isnull (@tmpRequireQty,0)- isnull (@tmpReturnQty,0)- isnull (@DeliveryQty,0) if(@tmpQty<0) BEGIN SET @Flag=@MatCode; BREAK;; END FETCH NEXT FROM DeliveryCursor INTO @MatCode,@DeliveryQty END CLOSE DeliveryCursor DEALLOCATE DeliveryCursor if @Flag= '0' UPDATE t_WM_Delivery SET DeliverySts=2 WHERE DeliveryCode=@DeliveryCode COMMIT TRAN SELECT @Flag; END TRY BEGIN CATCH SELECT @ERROR_MESSAGE = ERROR_MESSAGE(); RAISERROR (@ERROR_MESSAGE , 16, 1); SELECT -1; END CATCH END |
实例三(该实例来自网络):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ---游标循环遍历-- begin declare @a int ,@error int declare @ temp varchar (50) set @a=1 set @error=0 begin tran --申明事务 --申明游标为Uid declare order_cursor cursor for ( select [Uid] from Student) --打开游标-- open order_cursor --开始循环游标变量-- fetch next from order_cursor into @ temp while @@FETCH_STATUS = 0 --返回被 FETCH语句执行的最后游标的状态-- begin update Student set Age=20+@a,demo=@a where Uid=@ temp set @a=@a+1 set @error= @error + @@ERROR --记录每次运行sql后是否正确,0正确 fetch next from order_cursor into @ temp --转到下一个游标 end if @error=0 begin commit tran --提交事务 end else begin rollback tran --回滚事务 end close order_cursor --关闭游标 deallocate order_cursor --释放游标 end |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本