每行返回执行存储过程?

时间:2016-11-14 16:50:14

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

我有一个存储过程,它从用户那里获取两个参数,即referenceNumberdestinationLocation,其中referenceNumber是行的唯一标识符,destinationLocation是请求的项目将被交付。请参阅下面的表格tblStockMove

deliveryID | ProductID | SourceLocation | DestinationLocation | Quantity | deliveryStart | deliveryEnd | ReferenceNumber | Status | Requestor | Receiver | ControlNumber | MoveType | ProductCode
13         | 1         |    WAREHOUSE   | Burger Queen        | 5        | 2016-11-14    | NULL        | CTRL_MULTI01    | PENDING| john.doe  | NULL     | CTRL_MULTI01  | MULTIPLE | 19000207
14         | 1         |    WAREHOUSE   | DcMo                | 4        | 2016-11-14    | NULL        | CTRL_MULTI01    | PENDING| john.doe  | NULL     | CTRL_MULTI01  | MULTIPLE | 19000207
15         | 1         |    WAREHOUSE   | Strapbucks          | 10       | 2016-11-14    | NULL        | CTRL_MULTI01    | PENDING| john.doe  | NULL     | CTRL_MULTI01  | MULTIPLE | 19000207
16         | 2         |    WAREHOUSE   | DcMo                | 6        | 2016-11-14    | NULL        | CTRL_MULTI01    | PENDING| john.doe  | NULL     | CTRL_MULTI01  | MULTIPLE | 19000209

我想要实现的是批量插入所有这些记录到各自的目的地位置,如果该位置具有相同的项目,则更新数量。

因此,我制作了这个存储过程,它执行一系列插入,更新和删除:

CREATE procedure updateTBLStock
    @referenceNumber nvarchar(50),
    @destinationLocation nvarchar(50)
as begin
    --1) insert non existing items to a temporary table
      INSERT INTO tblTempStockList
      SELECT b.ProductID, a.ProductName, a.ProductCode, b.Quantity, a.UnitOfMeasure, 
      a.Provider, a.Category, a.ExpirationDate, b.DestinationLocation, b.ReferenceNumber
            FROM tblStockMove b
            inner join tblProducts_warehouse a on b.ProductCode = a.ProductCode 
            where b.ReferenceNumber = @referenceNumber
            and NOT EXISTS (Select a.ProductCode from tblProducts_establishments a
            where b.ProductCode = a.ProductCode 
            and a.Location = @destinationLocation
            and b.ReferenceNumber = @referenceNumber
            and b.MoveType = 'MULTIPLE')

    --2) update items' quantity if they already exist in the destination location
            UPDATE tblProducts_establishments 
            SET Quantity = a.Quantity + b.Quantity
            from tblProducts_establishments a 
            left join tblStockMove b
            on a.ProductCode = b.ProductCode 
            where b.ReferenceNumber = @referenceNumber 
            and b.MoveType = 'MULTIPLE' 
            and a.Location = @destinationLocation
            and EXISTS (Select a.ProductCode from tblProducts_establishments a 
            where b.ProductCode = a.ProductCode and a.Location = @destinationLocation
            and b.ReferenceNumber = @referenceNumber and b.MoveType = 'MULTIPLE')       

    --3) Insert the row from the temporary table to the main table

            INSERT INTO tblProducts_establishments (ProductID, ProductName, ProductCode, Quantity, UnitOfMeasure, Date, Provider, Category, ExpirationDate, Status, Location)
            SELECT ProductID, ProductName, ProductCode, Quantity, UnitOfMeasure, getdate(), Provider, Category, ExpirationDate, null, Location FROM tblTempStockList where ReferenceNumber = @referenceNumber and Location = @destinationLocation

    --4) Empty the temporary table
            DELETE FROM tblTempStockList where ReferenceNumber = @referenceNumber and Location = @destinationLocation

此查询运行良好 IF 一个referenceNumber中只有一行(项),但如果有多个条目,则无法正确插入。

所以我尝试使用游标,但是它会为每个DestinationLocation插入重复的ProductID。

declare @destinationLocation nvarchar(50)
declare @referenceNumber nvarchar(50)

declare cur CURSOR LOCAL for
    select DestinationLocation, ReferenceNumber from tblStockMove where ControlNumber = 'CTRL_MULTI01'
open cur

fetch next from cur into @destinationLocation, @referenceNumber

while @@FETCH_STATUS = 0 BEGIN

    execute updateTBLStock @referenceNumber, @destinationLocation

    fetch next from cur into @destinationLocation, @destinationLocation
END

close cur
deallocate cur

我的问题是,如何使用上面的光标成功调用存储过程?如何从存储过程所需的游标中传递两个变量?

1 个答案:

答案 0 :(得分:0)

通过将表创建为类型,将您的参数作为表类型变量传递 像

 CREATE TYPE dbo.TBLStockType AS TABLE
 (
    referenceNumber nvarchar(50),
    destinationLocation nvarchar(50)
  )

GO

然后在您的程序中使用此类型

CREATE procedure updateTBLStock
@referenceNumber TBLStockType READONLY,
@destinationLocation TBLStockType READONLY
as begin

    --your code here 
end

通过使用它,您可以一次传递多个参数。 将参数传递如下

DECLARE @StockType AS TBLStockType

INSERT INTO @StockType
SELECT 'CTRL_MULTI01','DcMo'
union all 
select 'CTRL_MULTI01','DcMo'

--then execute proc

EXEC updateTBLStock @StockType