まず、私はカーソルが一般的に悪であり、使用されるべきではないことをよく認識していると述べます。この特定の問題に対するセットベースの解決策を考え出すことはできませんでした。セットベースの操作を行うように私に教えてもらえれば、この特定の問題をどのようにコード化するかを教えてもらえればそれだけです。ネストされたカーソルを使用して「無効なオブジェクト名」を取得する必要があります
基本的に、私は購入する必要があるいくつかの在庫品を持っています。私は最も安い利用可能な価格に基づいて購入したいと思っています。ここで私はサプライヤーの価格と在庫レベルを知っています。また、可能な場合はパックサイズで購入したいというパックサイズの問題もあります。
私は既に#needorders
に購入する必要がある物品のリストと、供給者の在庫レベルと価格を#orderedprices
に引き出しました。私はカーソルCUR_NEEDED
を反復処理し、二次カーソルCUR_AVAILABLE
作成しています下:
DECLARE CUR_NEEDED CURSOR LOCAL SCROLL_LOCKS
FOR
SELECT GoodID
, ConditionID
, QuantityToShip
, OrderStatusID
, RetailerID
, PackSize
FROM #needorders
ORDER BY GoodID
, ConditionID
, PurchaseDate DESC
FOR UPDATE
OPEN CUR_NEEDED
FETCH NEXT FROM CUR_NEEDED INTO @GoodID, @ConditionID, @QuantityToShip, @OrderStatusID, @RetailerID, @PackSize
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE CUR_AVAILABLE CURSOR LOCAL SCROLL_LOCKS
FOR
SELECT SupplierStocklistItemID
, SupplierID
, StockLevel
, SupplierCurrencyID
, CostPrice
FROM #orderedprices
WHERE #orderedprices.GoodID = @GoodID
AND #orderedprices.ConditionID = @ConditionID
AND #orderedprices.StockLevel > 0
ORDER BY #orderedprices.PriceRank
FOR UPDATE
OPEN CUR_AVAILABLE
FETCH NEXT FROM CUR_AVAILABLE INTO @SupplierStocklistItemID, @SupplierID, @StockLevel, @SupplierCurrencyID, @CostPrice
WHILE @@FETCH_STATUS = 0
BEGIN
/*
Buy as many @PackSize as we need to cover how many we require, unless the supplier
only has a certain number, in which case buy that number.
E.g., need 14, pack size 5, 2 suppliers
Supplier A has 11
Supplier B has 40
Buy 9 from Supplier A, with our remaining need being 3.
Buy 5 from supplier B, with our remaining need being -2
*/
--feed rows into #supplierpurchasesbase while @StockLevel > 0
--Figure out how many we need to buy, based upon PackSize
IF @QuantityToShip % @PackSize > 0
BEGIN
SET @Buy = @QuantityToShip - @QuantityToShip % @PackSize + @PackSize
END
ELSE
BEGIN
SET @Buy = @QuantityToShip
END
IF @StockLevel < @Buy
BEGIN
--PRINT 'Supplier only has ' + CAST(@StockLevel AS VARCHAR) + ' for us to buy.'
SET @Buy = @StockLevel
END
INSERT INTO #supplierpurchasesbase (
GoodID
, ConditionID
, SupplierStocklistItemID
, Quantity
, SupplierID
, SupplierCurrencyID
, CostPrice
, RetailerID)
SELECT @GoodID
, @ConditionID
, @SupplierStocklistItemID
, @Buy
, @SupplierID
, @SupplierCurrencyID
, @CostPrice
, @RetailerID
--update @QuantityToShip & the row in CUR_AVAILABLE
IF @StockLevel <= @Buy
BEGIN
UPDATE CUR_AVAILABLE
SET StockLevel = @StockLevel - @Buy
WHERE CURRENT OF CUR_AVAILABLE
SET @QuantityToShip = 0
END
ELSE
BEGIN
UPDATE CUR_AVAILABLE
SET StockLevel = 0
WHERE CURRENT OF CUR_AVAILABLE
SET @QuantityToShip = @QuantityToShip - @Buy
END
--update the stocklevel so we don't see the thing again if we've used it up.
IF @QuantityToShip = 0 --Don't need any more
BEGIN
UPDATE CUR_NEEDED
SET OrderStatusID = @StatusPendingPO
WHERE CURRENT OF CUR_NEEDED
BREAK
END
ELSE --Need more, move next, if we can
FETCH NEXT FROM CUR_AVAILABLE INTO @SupplierStocklistItemID, @SupplierID, @StockLevel, @SupplierCurrencyID, @CostPrice
END
CLOSE CUR_AVAILABLE
DEALLOCATE CUR_AVAILABLE
FETCH NEXT FROM CUR_NEEDED INTO @GoodID, @ConditionID, @QuantityToShip, @OrderStatusID, @RetailerID, @PackSize
END
CLOSE CUR_NEEDED
DEALLOCATE CUR_NEEDED
私はに実行している問題は、私は、私はエラー
無効なオブジェクト名「を取得してい得るということですがCUR_AVAILABLE '
CURRENT OF CUR_AVAILABLE
を更新しようとしています。
CUR_AVAILABLE
カーソルを@CUR_AVAILABLE
として定義しようとしましたが、別のエラーが発生しました。私はCUR_NEEDED
のWHILE
ループの外側のCUR_AVAILABLE
カーソルを定義しようとしましたが、カーソルを閉じる/割り当てを解除しないようにしました。これは動作していないようです。
ここで私が間違っていると思うアイデアは、(セットベースの解決策がない限り、セットを使用している以外は)
ありがとう、アンドリー!私はこれを打つつもりで、もし私が2つのカーソルの機能を複製することができれば、私はあなたの答えにフラグを立てるでしょう - カーソルを扱う方が望ましいでしょう(私は多分3過去15年間、私はこのような人に仕事をさせるような問題に遭遇しました)! –