在不使用SQL Cursor的情况下插入行和更新表

时间:2011-06-16 02:00:12

标签: sql sql-server sql-server-2005 stored-procedures cursor

我正在尝试创建一个MS SQL 2005存储过程,以便从仓库为订单中的特定组件分配库存。有多批库存可供使用,必须按特定顺序使用。我可以遍历可用的股票并分配,直到订单完成,但我试图考虑更多基于顺序的集合,并避免使用CURSOR。

这是我的查询,它可以获取特定订单组件的仓库库存;

SELECT 
        STOCK.ComponentId,
        STOCK.StockId,
        STOCK.ExpiryDate, 
        STOCK.BatchNo, 
        STOCK.StockQty, 
        ORDER_ITEMS.OrderQty        
    FROM 
        STOCK 
        JOIN ORDER_ITEMS ON ORDER_ITEMS.ComponentId = STOCK.ComponentId 
    WHERE 
        STOCK.WarehouseId = @WarehouseId 
        AND STOCK.StockQty > 0
        AND ORDER_ITEMS.OrderItemId = @OrderItemId

我一直把它放到临时表中或者用查询创建一个CTE并应用ORDER BY子句来获取需要用完的库存。这给了我一个结果集:

ComponentId | StockId | ExpiryDate | BatchNo  | StockQty | OrderQty
-------------------------------------------------------------------
359         | 3107    | 2013-10-01 | 132435-1 | 20       | 50
359         | 3215    | 2013-10-01 | 154558-1 | 100      | 50
359         | 3216    | 2014-01-01 | 154689-1 | 100      | 50

我需要做的是使用尽可能多的批次库存将记录插入STOCK_ALLOCATED表中以完成订单数量。在上面的例子中,我将使用第一行中的所有20,然后从第二行需要30。

这需要在STOCK_ALLOCATED表中插入两个记录,其中OrderItemIdStockId和两个批次的数量(20和30)也会减少库存数量适当地在STOCK表中。

假设有必要的交易以保持库存表的一致性,有一种方法可以进行插入和更新,而无需使用CURSOR循环并跟踪我已经分配了多少库存以及我还需要多少库存?

1 个答案:

答案 0 :(得分:2)

这是一个适合您的测试样本:

SELECT  
    StockID,
    Quantity
FROM (
    SELECT  
        StockID,
        CASE 
            WHEN OrderQty - PreviousQty <= 0 THEN 0
        ELSE 
                CASE 
                    WHEN OrderQty - PreviousQty <= Stock 
                    THEN OrderQty - PreviousQty 
                ELSE
                    Stock 
                END
        END Quantity
    FROM (
        SELECT  
            a.StockID,
            a.Stock,
            a.OrderQty,
            a.OrderByField,
            ISNULL(SUM(b.Stock), 0) PreviousQty
        FROM    
            @Table a
            LEFT JOIN @Table b ON a.OrderByField > b.OrderByField
        GROUP BY a.StockID,
            a.Stock,
            a.OrderQty,
            a.OrderByField
        ) Orders
    ) Orders
WHERE   Quantity > 0

基本上,您需要加入自己获得的结果,这样您就可以对先前保留数量的数量求和,然后从StockQty中减去它,以确定您仍需要实现的结果。

但是,为了做到这一点,您需要一个唯一的OrderByField,以便您可以准确地过滤掉以前的StockQty值。如果您没有可以使用的存储值,则可以使用ROW_NUMBER() OVER派生它。如果是这种情况,请告诉我您是否需要帮助。