zoukankan      html  css  js  c++  java
  • sql server 存储过程使用游标记录

    sql server 存储过程使用游标记录--方便下次参考使用

    游标的组成:

    • 声明游标
    • 打卡游标
    • 从一个游标中查找信息
    • 关闭游标
    • 释放游标

    游标类型:

    • 静态游标
    • 动态游标
    • 只进游标
    • 键集驱动游标

    静态游标:静态游标的完整结果集在游标打开时建立在tempdb中。静态游标总是按照游标打开时的原样显示结果集。

    静态游标在滚动期间很少或根本监测不到变化,虽然在tempdb中存储了整个游标,但消耗的资源很少。尽管动态游标使用tempdb的程度最低,在滚动期间它能够监测到所有变化,单消耗的资源也更多。

    键集驱动游标介于二者之间,它能够监测到大部分的变化,但比动态游标消耗更少的资源。

    动态游标:与静态游标相对。当滚动游标时,动态游标反映结果集中所作的所有更改。结果集中的行数据值、顺序和成员在每次提取时都会改变。所有用户做的全部update、insert、delete语句均通过游标可见。

    只进游标:只进游标不支持滚动,它只支持游标从头到尾顺序提取。只在从数据库中提取出来后才能进行检索。对所有由当前用户发出或其他用户提交,并影响结果集中的行的insert、update、delete语句,其效果在这些行从游标中提取时是可见的。

    键集驱动游标:打开游标时,键集驱动游标中的成员和行顺序是固定的。键集驱动游标由一套被称为键集的唯一标识符(键)控制。键由以唯一方式在结果集中标识行的列构成。键集是游标打开时来自所有适合select语句的行中的一系列键值,键集驱动

    游标打开时建立在tempdb中。对非键集列中的数据值所做的更改(由游标所有者更改或其他用户提交)在用户滚动游标时是可见的,在游标外对数据库所做的插入在游标内是不可见的,除非关闭并重新打开游标。

    参考实例如下:

    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
    

      

      

      实例二

    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
    

    实例三(该实例来自网络):

    ---游标循环遍历--
    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
    

      

  • 相关阅读:
    oracle 数据库服务名怎么查
    vmware vsphere 6.5
    vSphere虚拟化之ESXi的安装及部署
    ArcMap中无法添加ArcGIS Online底图的诊断方法
    ArcGIS中字段计算器(高级计算VBScript、Python)
    Bad habits : Putting NOLOCK everywhere
    Understanding the Impact of NOLOCK and WITH NOLOCK Table Hints in SQL Server
    with(nolock) or (nolock)
    What is “with (nolock)” in SQL Server?
    Changing SQL Server Collation After Installation
  • 原文地址:https://www.cnblogs.com/YYkun/p/9685765.html
Copyright © 2011-2022 走看看