一、游标的作用:
Select时,返回的是一个结果集,若需要为结果集返回的过程中,读取到一行数据。需要对此行数据进行处理,比如按读取到的数据作为查询条件返回一个查询结果集等等,应用都需要用到游标。
游标可允许 用户 查询下一行、上一行、第一行或最后一行,并对这些读取到的行进行处理。
二、游标举例

CREATE FUNCTION GetMRPlnFullBom  --创建一函数,根据单据电键查询单据中每行,并对每行数据进行处理。   
(  
	@DocEntry int  
)  
RETURNS @TAB TABLE   -- 将最终查询的结果集定义临时表,返回。   
(  
    DocEntry int,  
    LineNum int,  
    LineNumLevel nvarchar(100),  
    ItmID nvarchar(20),   
    ItmName nvarchar(100),  
    LineType char(1),  
    Qty numeric(19,9),  
    BomLevel int,  
    ParentEntry int,  
    ParentItmID nvarchar(20),  
    TopEntry int,  
    TopItmID nvarchar(20) ,  
    BaseEntry int ,  
    BaseLineNum int ,  
    BaseType int  
)  
AS  
BEGIN  
     Declare  @ItmID varchar(50) , @Qty int ,@LineNum int ,@ObjType int   --声明局部变量   
     --声明一游标,声明游标时 XXX前不能加@,比如下面的MRPlnA_ItmID ,格式是DECLARE XXX CURSOR FOR        
     DECLARE MRPlnA_ItmID CURSOR FOR   
     SELECT ItmID , Qty ,LineNum , ObjType FROM MRPlnA  Where DocEntry = @DocEntry --语句要在DECLARE XXX CURSOR FOR与OPEN XXX之间。   
     Open MRPlnA_ItmID      --打开游标   
     FETCH NEXT FROM MRPlnA_ItmID INTO @ItmID , @Qty ,@LineNum , @ObjType --FETCH NEXT FROM XXX INTO ... 更新游标指定记录即换行,并将Select出来的数据,存入临时变量中。  FETCH格式上除了NEXT还有PRIOR、FRIST、LAST。分别是上一行、第一行及最后一行。   
     WHILE @@FETCH_STATUS = 0 --@@FETCH_STATUS全局变量,用于查询FETCH最后一次状态,控制循环。当读取完时是0,读取失败是-1,记录被删除是-2。   
     BEGIN  
         Insert Into @TAB  
         Select DocEntry,LineNum,LineNumLevel,ItmID,ItmName,LineType,Qty*@Qty,BomLevel,ParentEntry,   
                ParentItmID,TopEntry,TopItmID , @DocEntry SourceEntry ,@LineNum BaseLineNum ,@ObjType BaseType   
         From GetBomFullItems(@ItmID, 'V 1.0', GetDate()) TD --GetBomFULLItmes是另一查询函数。   
         FETCH NEXT FROM MRPlnA_ItmID INTO @ItmID  , @Qty ,@LineNum , @ObjType -- Select移到下一行。   
     END  
     CLOSE MRPlnA_ItmID       --关闭游标   
     DEALLOCATE MRPlnA_ItmID  --释放游标   
     RETURN
END

参考:https://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html
循环临时表:

USE [LT]
GO
/****** Object:  StoredProcedure [dbo].[proc_StoreTaskToLT]    Script Date: 2021/9/27 15:15:54 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

--https://www.cnblogs.com/lusunqing/p/3660190.html
ALTER proc [dbo].[proc_StoreTaskToLT]
as

declare @ASNOutId int,
@OrderId bigint,
@asncount int,
@storeoutlinecount int,
@storeinventorycount int,
@k int,
@j int,
@l int,
@TenantId int,
@OutLineId bigint,
@DeliveryQuantity int,
@IsPicked bit,
@Comment nvarchar(max),
@Remark nvarchar(max),
@CreatorName nvarchar(max),
@DeleterName nvarchar(max),
@LastModifierName nvarchar(max),
@LastModificationTime datetime,
@IsDeleted bit,
@DeleterUserId bigint,
@DeletionTime datetime,
@LastModifierUserId bigint,
@CreationTime datetime,
@CreatorUserId bigint,
@ItemId bigint,
@LocationId bigint,
@CalQuantity int,
@InventoryId bigint,
@CurrentQuantity int
-- 查找所有已同步到WMS_trial,并且已经出库的出库单
select * into #temp_ASNOutIds from
(
	select ASNOutId,ROW_NUMBER() over(order by ASNOutId asc) as rowindex1 from LMS.WMS.dbo.ASNOut 
	where ASNOutId in
	(
		select AsnId from dbo.Store_TaskOrderOut 
		where AsnId is not null and Is2Wms is not null 
		and Is2Wms=1 and (Is2A56 is null or Is2A56=0)
	)
	and Time_Outbound is not null
) as tab
select @asncount = COUNT(1) from #temp_ASNOutIds
set @k = 1
while (@asncount >= @k)
	begin
		select @ASNOutId=ASNOutId from #temp_ASNOutIds where rowindex1=@k
		--更改 Store_TaskOrderOut Is2A56 为 1,更改 Store_OutLine DeliveryQuantity 实发数量
		update dbo.Store_TaskOrderOut set Is2A56=1 where AsnId=@ASNOutId

		update t1 set t1.DeliveryQuantity=t3.PickedQty 
		from dbo.Store_OutLine as t1 
		inner join dbo.Store_TaskOrderOutLine as t2 on t1.Id = t2.LineId
		inner join LMS.WMS.dbo.CargoOut as t3 on t2.CargoId = t3.CargoOutId
		where t2.TaskId in
		(
			select Id from dbo.Store_TaskOrderOut where AsnId=@ASNOutId
		)

		update sl set sl.DeliveryQuantity=ISNULL(sl.DeliveryQuantity,0)+t3.PickedQty,OutboundDiscountAmount = CONVERT(DECIMAL(18,2),ROUND(CONVERT(DECIMAL(18,2),ISNULL(sl.DeliveryQuantity,0)+t3.PickedQty)/ConfirmQuantity*SalesDiscountAmount,2)) 
		from dbo.Store_OutLine as t1 
		INNER JOIN dbo.Marketing_SalesOut so ON t1.Id=so.OutLineId
		INNER JOIN dbo.Marketing_SalesLine sl ON sl.Id=so.SalesLineId
		inner join dbo.Store_TaskOrderOutLine as t2 on t1.Id = t2.LineId
		inner join LMS.WMS.dbo.CargoOut as t3 on t2.CargoId = t3.CargoOutId
		where t2.TaskId in
		(
			select Id from dbo.Store_TaskOrderOut where AsnId=@ASNOutId
		)

		--Milestone Outbound 出库 120
		update t1 set t1.Milestone=120
		from dbo.Store_Out as t1
		where t1.Id in (select OrderId from dbo.Store_TaskOrderOut where AsnId=@ASNOutId)

		select *,ROW_NUMBER() over(order by OutLineId asc) as rowindex2 into #temp_Store_OutLine from
		(
			select 
			t1.[TenantId]
           ,t1.Id as [OutLineId]
           ,t1.DeliveryQuantity
           ,1 as [IsPicked]
           ,t1.[Comment]
           ,t1.[Remark]
           ,t1.[CreatorName]
           ,t1.[DeleterName]
           ,t1.[LastModifierName]
           ,t1.[LastModificationTime]
           ,t1.[IsDeleted]
           ,t1.[DeleterUserId]
           ,t1.[DeletionTime]
           ,t1.[LastModifierUserId]
           ,t1.[CreationTime]
           ,t1.[CreatorUserId]
		   ,t1.ItemId
		   ,t2.LocationId
			from dbo.Store_OutLine as t1 
			inner join dbo.Store_Out as t2 on t1.OutId = t2.Id
			where t1.OutId in(select OrderId from dbo.Store_TaskOrderOut where AsnId=@ASNOutId)
		) as tab2
		--循环出库明细
		select @storeoutlinecount = COUNT(1) from #temp_Store_OutLine
		set @j = 1
		while (@storeoutlinecount >= @j)
		begin
			--出库明细
			select @ItemId=ItemId,@LocationId=LocationId,
			@TenantId =TenantId,@OutLineId =OutLineId,@DeliveryQuantity =DeliveryQuantity,@IsPicked =1,
			@Comment =Comment,@Remark =Remark,@CreatorName =CreatorName,@DeleterName =DeleterName,@LastModifierName =LastModifierName,
			@LastModificationTime =LastModificationTime,@IsDeleted =IsDeleted,@DeleterUserId =DeleterUserId,@DeletionTime =DeletionTime,
			@LastModifierUserId =LastModifierUserId,@CreationTime =CreationTime,@CreatorUserId=CreatorUserId
			from #temp_Store_OutLine where rowindex2=@j
			--库存明细
			select *,ROW_NUMBER() over(order by InboundDate asc) as rowindex3 into #temp_Store_Inventory
			from
			(
				select Id,CurrentQuantity,ItemId,LocationId,InboundDate
				from dbo.Store_Inventory where ItemId=@ItemId and LocationId=@LocationId
			) as tab3
			--循环扣除库存
			select @storeinventorycount = COUNT(1) from #temp_Store_Inventory
			set @l = 1
			while(@storeinventorycount>=@l)
			begin
				select @CurrentQuantity=CurrentQuantity,@InventoryId=Id from #temp_Store_Inventory where rowindex3=@l
				if(@DeliveryQuantity>=@CurrentQuantity)
				begin
					set @CalQuantity = @CurrentQuantity
					set @DeliveryQuantity = @DeliveryQuantity - @CalQuantity
					
				end
				else
				begin
					set @CalQuantity = @DeliveryQuantity 
					set @DeliveryQuantity=0
				end
				--插入[Store_PickingList],扣除Store_Inventory库存CurrentQuantity和AvailableQuantity,@DeliveryQuantity减去@CalQuantity
				INSERT INTO [dbo].[Store_PickingList]
				([TenantId]
				,[OutLineId]
				,[InventoryId]
				,[Quantity]
				,[IsPicked]
				,[Comment]
				,[Remark]
				,[CreatorName]
				,[DeleterName]
				,[LastModifierName]
				,[LastModificationTime]
				,[IsDeleted]
				,[DeleterUserId]
				,[DeletionTime]
				,[LastModifierUserId]
				,[CreationTime]
				,[CreatorUserId])
				values(
				@TenantId,
				@OutLineId ,
				@InventoryId,
				@CalQuantity,
				@IsPicked,
				@Comment,
				@Remark,
				@CreatorName,
				@DeleterName,
				@LastModifierName,
				@LastModificationTime,
				@IsDeleted,
				@DeleterUserId,
				@DeletionTime ,
				@LastModifierUserId,
				@CreationTime,
				@CreatorUserId
				);
				update dbo.Store_Inventory set CurrentQuantity=CurrentQuantity-@CalQuantity,AvailableQuantity = AvailableQuantity - @CalQuantity  where Id=@InventoryId;
				update dbo.StockBalances set CurrentQuantity = CurrentQuantity - @CalQuantity
				where LocationId=@LocationId and ItemId=@ItemId and TenantId=@TenantId

				if(@DeliveryQuantity=0)
				begin
					break
				end
				set @l = @l + 1
			end
			drop table #temp_Store_Inventory
			set @j = @j + 1
		end
		drop table #temp_Store_OutLine
		set @k = @k + 1
	end
drop table #temp_ASNOutIds--删除临时表

  

posted on 2016-04-07 10:02  邢帅杰  阅读(257)  评论(0编辑  收藏  举报