为什么我的游标不返回第一行值?

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子句构造行。