循环遍历记录以执行存储过程并存储结果

Looping through records to execute a stored procedure and store the result

我有一个存储过程 sp_OrderPrice_Calc,它接受一个 OrderNumber 和 returns 一个标量值 Order Price。我正在尝试循环上面的存储过程以获取订单号列表 而无需 使用游标。

我有以下逻辑,但输出不符合预期。我真的很感激任何 suggestions/changes.

---------------------------------------------------------------------------------
DECLARE @orderInfo AS TABLE 
                      (
                          ID INT IDENTITY(1,1), 
                          CompanyName VARCHAR(40), 
                          OrderNumber VARCHAR(40), 
                          DeliveryType VARCHAR(40), 
                          OrderPrice DECIMAL(6,1)
                      )

INSERT INTO @orderInfo (CompanyName, OrderNumber, DeliveryType)
    SELECT CompanyName, OrderNumber, DeliveryType
    FROM OrderData

DECLARE @ID INT = 1, @OrderNumber VARCHAR(40), @OrderPrice DECIMAL(6,1)

WHILE @ID IS NOT NULL
BEGIN
    SELECT @OrderNumber = OrderNumber
    FROM @orderInfo 
    WHERE ID = @ID
   
    INSERT INTO @orderInfo (OrderPrice)
       EXEC sp_OrderPrice_Calc @Order_Number = @OrderNumber, @Order_Price  = @OrderPrice
   
    SELECT @ID = MIN(ID) 
    FROM @OrderInfo 
    WHERE ID > @ID; 
END

SELECT * FROM @OrderInfo
---------------------------------------------------------------------------------

注意: 我已经创建了存储过程,它应该将 @Order_Number 作为输入,将 @order_Price 作为输出,我在上面的逻辑中使用了它

例如

CREATE PROCEDURE [dbo].[spCDS_TP_TW_limit] 
     @Order_Number VARCHAR(50) = '',
     @order_Price decimal(6,1) OUTPUT
AS

以上逻辑为输出中的每个 Order_Number 记录返回“Null”

CompanyName  OrderNumber  DeliveryType  OrderPrice
--------------------------------------------------
  ABBCCC      123456        Standard     NULL
  DDDDEE      147852        Standard     NULL
  EEEFFF      159635        Priority     NULL
  FFFFGG      163589        Ground       NULL

你这里有几个误区。

首先,您需要了解,当您使用 insert into table (columns...) exec procedure 形式时,插入的内容是存储过程的 结果集 。换句话说,过程中 select 语句的任何结果。如果您的存储过程没有结果集,则没有可插入的内容。请注意,output 参数与结果集 not 相同。观察如果 运行 以下批次会发生什么:

create table t(result varchar(30))
go

create  procedure p (@result varchar(30) = null output) as 
begin 
    set @result = 'this is the output parameter';
    select 'this is the result set'; 
end
go

declare @param varchar(30);
insert t (result) exec p @param output;
select * from t; 
select @param;

在此脚本执行结束时,table t 将有一行值为““这是结果集”。 @param 变量的值将是“这是输出参数”。

好的,现在让我们看看您的程序中发生了什么。

您使用 insert ... exec 模式,因此存储过程的结果集将 插入 作为新行到您的 @orderInfo table.

但是从您所写的内容来看,您似乎打算将价格作为 output 参数值提供,供您的 @orderPrice 变量使用。它实际上不会这样做,因为您还没有将它用作输出参数。您遗漏了 output 关键字。

我希望您的存储过程根本没有结果集。这意味着没有任何内容被插入 table.

即使存储过程做了return一个结果集,你也在做一个insertinsert 将创建新行,它不会更新现有行的 OrderPrice 列的值。

您可能打算做的是:

While @ID IS NOT NULL
 BEGIN
   Select @OrderNumber = OrderNumber;
   From @orderInfo Where ID = @ID;
      
   Exec sp_OrderPrice_Calc 
      @Order_Number = @OrderNumber, 
      @Order_Price  = @OrderPrice output; -- output keyword is required both here and in the procedure definition

   update @orderInfo set OrderPrice = @orderPrice where ID = @ID; -- update, not insert.

   Select @ID = MIN(ID) From @OrderInfo where ID > @ID;
 END

这里可能有更好的解决方案。如果您的存储过程可以重写为 user defined function,则根本不需要循环:

select CompanyName, OrderNumber, DeliveryType, OrderPrice = myOrderPriceFunction(...)
From OrderData;