最初に、カーソルは一般的に悪であり、使用すべきではないことをよく認識していることをすぐに述べさせてください。 . セットベースの操作を行うように言われたとしても、この特定の問題をどのようにコーディングするかを教えていただければ、私は大賛成です。
基本的に、購入する必要がある在庫商品がいくつかあります。サプライヤーの価格と在庫レベルを知っている、最も安い価格に基づいて購入したいと考えています。パックサイズの問題もあり、できればパックサイズで購入したいです。
に購入する必要があるもののリストと#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_AVAILABLE
外側でカーソルを定義しようとしましたが、カーソルを閉じたり割り当てを解除したりしないようにしました。これはどれも機能していないようです。WHILE
CUR_NEEDED
ここで、私が間違っているアイデアはありますか(セットベースのソリューションを持っていない限り、セットを使用しないこと以外)?