一、游标的作用:
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--删除临时表
浙公网安备 33010602011771号