为什么我的游标不返回第一行值?
Why my cursor isn't returning the first row values?
我有一个游标,以便根据每个项目的所需数量来分隔行,这工作得很好,除了它不 return 第一行,相反,如果例如,行的数量值为 3,它将其添加到最后一行。我的代码如下:
DECLARE curCURSOR CURSOR
FOR
SELECT ITEM, CITY, OPEN_QUANTITY, MODEL, PROMISE , SALES_ORDER , LINE_NUMBER, DESCRIPTION, CARRIER FROM T_tmpShipReporCommAssy
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @pSite
AND FG_AVAILABLE > 0
ORDER BY PROMISE, SALES_ORDER, LINE_NUMBER
OPEN curCURSOR
FETCH curCURSOR INTO @ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER
IF EXISTS(SELECT 1 FROM AvailToShipPalletsSN)
BEGIN
DELETE FROM AvailToShipPalletsSN
DBCC CHECKIDENT ('[AvailToShipPalletsSN]', RESEED, 0);
END
DECLARE @e INT
SET @e = 0
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH FROM curCURSOR INTO @ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER
WHILE (@e < @required_quantity)
BEGIN
INSERT INTO AvailToShipPalletsSN (item, city, required_quantity, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER) values
(@ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER)
SET @e = @e + 1
END
SET @e = 0
END
CLOSE curCURSOR
DEALLOCATE curCURSOR
现在,当我 运行 一个 select 计数到原始 table 和生成的一个时:
SELECT MODEL, SUM(OPEN_QUANTITY) FROM T_tmpShipReporCommAssy
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @psite
AND FG_AVAILABLE > 0
AND PROMISE <= @pdate
GROUP BY MODEL
SELECT model, COUNT(required_quantity) FROM AvailToShipPalletsSN
group by model
它 return 给我以下结果:
(Table 数量正确)
CMF200M 10
CMF010M 2
CMF200A 1
H200F 2
(Table 由我的光标生成)
CMF200M 8
CMF010M 2
CMF200A 1
H200F 4
我真的不知道如何解决这个问题,如果能就此主题提供一些帮助,我将不胜感激
问题是您在打开游标后立即获取了一行,但未对获取的值执行任何操作。所以你最终错过了第一行。要更正此问题,请按以下方式重新组织代码:
-- first delete the other table
if exists(select ....)
begin
delete ...
end
-- then, declare variables, open the cursor, etc.
declare curCURSOR cursor for ...
declare @e int = 0
open curCURSOR
-- then start fetching. use the following pattern:
fetch from curCURSOR into @...
while @@FETCH_STATUS = 0
begin
-- do your thing:
while @e < @required_quantity
...
-- then, after you did your thing
-- and just before the end of the while @@fetch_status block,
-- fetch again
fetch from curCURSOR into @...
end
-- finally close, deallocate, etc.
close ...
deallocate ...
这解决了缺少第一行的问题。
第二个问题的原因可能是您向不在游标中的查询添加了条件:PROMISE <= @pdate
。
也就是说,在 @pdate
之后可能有一些带有 promise 的行被插入到第二个 table 中,但是当您使用它查询第一个 table 时不显示条件。
游标非常慢且效率低下,编码起来也很麻烦。
您可以完全消除对这种缓慢且不正确的游标的需要,方法是使用内联计数table。
这是您需要的全部代码:
IF EXISTS(SELECT 1 FROM AvailToShipPalletsSN)
BEGIN
TRUNCATE AvailToShipPalletsSN;
DBCC CHECKIDENT ('[AvailToShipPalletsSN]', RESEED, 0);
END;
WITH
L0 AS ( SELECT 1 AS c
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B ),
L2 AS ( SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B )
-- add more cross-joins if you need more than 65536 rows
INSERT INTO AvailToShipPalletsSN
(item, city, required_quantity, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER)
SELECT
ITEM, CITY, OPEN_QUANTITY, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER
FROM T_tmpShipReporCommAssy t
CROSS APPLY (
SELECT TOP (t.OPEN_QUANTITY) *
FROM L2
) nums
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @pSite
AND FG_AVAILABLE > 0;
本质上,它所做的是,对于基础 table 中的每一行,对其应用一堆行。添加的行数等于OPEN_QUANTITY
,使用交叉连接VALUES
子句构造行。
我有一个游标,以便根据每个项目的所需数量来分隔行,这工作得很好,除了它不 return 第一行,相反,如果例如,行的数量值为 3,它将其添加到最后一行。我的代码如下:
DECLARE curCURSOR CURSOR
FOR
SELECT ITEM, CITY, OPEN_QUANTITY, MODEL, PROMISE , SALES_ORDER , LINE_NUMBER, DESCRIPTION, CARRIER FROM T_tmpShipReporCommAssy
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @pSite
AND FG_AVAILABLE > 0
ORDER BY PROMISE, SALES_ORDER, LINE_NUMBER
OPEN curCURSOR
FETCH curCURSOR INTO @ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER
IF EXISTS(SELECT 1 FROM AvailToShipPalletsSN)
BEGIN
DELETE FROM AvailToShipPalletsSN
DBCC CHECKIDENT ('[AvailToShipPalletsSN]', RESEED, 0);
END
DECLARE @e INT
SET @e = 0
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH FROM curCURSOR INTO @ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER
WHILE (@e < @required_quantity)
BEGIN
INSERT INTO AvailToShipPalletsSN (item, city, required_quantity, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER) values
(@ITEM, @CITY, @required_quantity, @MODEL, @PROMISE, @SALES_ORDER, @LINE_NUMBER, @DESCRIPTION, @CARRIER)
SET @e = @e + 1
END
SET @e = 0
END
CLOSE curCURSOR
DEALLOCATE curCURSOR
现在,当我 运行 一个 select 计数到原始 table 和生成的一个时:
SELECT MODEL, SUM(OPEN_QUANTITY) FROM T_tmpShipReporCommAssy
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @psite
AND FG_AVAILABLE > 0
AND PROMISE <= @pdate
GROUP BY MODEL
SELECT model, COUNT(required_quantity) FROM AvailToShipPalletsSN
group by model
它 return 给我以下结果:
(Table 数量正确)
CMF200M 10
CMF010M 2
CMF200A 1
H200F 2
(Table 由我的光标生成)
CMF200M 8
CMF010M 2
CMF200A 1
H200F 4
我真的不知道如何解决这个问题,如果能就此主题提供一些帮助,我将不胜感激
问题是您在打开游标后立即获取了一行,但未对获取的值执行任何操作。所以你最终错过了第一行。要更正此问题,请按以下方式重新组织代码:
-- first delete the other table
if exists(select ....)
begin
delete ...
end
-- then, declare variables, open the cursor, etc.
declare curCURSOR cursor for ...
declare @e int = 0
open curCURSOR
-- then start fetching. use the following pattern:
fetch from curCURSOR into @...
while @@FETCH_STATUS = 0
begin
-- do your thing:
while @e < @required_quantity
...
-- then, after you did your thing
-- and just before the end of the while @@fetch_status block,
-- fetch again
fetch from curCURSOR into @...
end
-- finally close, deallocate, etc.
close ...
deallocate ...
这解决了缺少第一行的问题。
第二个问题的原因可能是您向不在游标中的查询添加了条件:PROMISE <= @pdate
。
也就是说,在 @pdate
之后可能有一些带有 promise 的行被插入到第二个 table 中,但是当您使用它查询第一个 table 时不显示条件。
游标非常慢且效率低下,编码起来也很麻烦。
您可以完全消除对这种缓慢且不正确的游标的需要,方法是使用内联计数table。
这是您需要的全部代码:
IF EXISTS(SELECT 1 FROM AvailToShipPalletsSN)
BEGIN
TRUNCATE AvailToShipPalletsSN;
DBCC CHECKIDENT ('[AvailToShipPalletsSN]', RESEED, 0);
END;
WITH
L0 AS ( SELECT 1 AS c
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B ),
L2 AS ( SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B )
-- add more cross-joins if you need more than 65536 rows
INSERT INTO AvailToShipPalletsSN
(item, city, required_quantity, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER)
SELECT
ITEM, CITY, OPEN_QUANTITY, MODEL, PROMISE, SALES_ORDER, LINE_NUMBER, DESCRIPTION, CARRIER
FROM T_tmpShipReporCommAssy t
CROSS APPLY (
SELECT TOP (t.OPEN_QUANTITY) *
FROM L2
) nums
WHERE [DESCRIPTION] like 'COM%ASSY%' AND CITY = @pSite
AND FG_AVAILABLE > 0;
本质上,它所做的是,对于基础 table 中的每一行,对其应用一堆行。添加的行数等于OPEN_QUANTITY
,使用交叉连接VALUES
子句构造行。