每次使用带有游标的存储过程更新一行时,每次调用存储过程

时间:2017-02-27 00:23:19

标签: sql stored-procedures cursor

我很擅长使用游标。 每次运行存储过程时,我只想让一行更改运费值(不是全部)。任何帮助将不胜感激。

[代码]

SELECT * FROM NorthWind.dbo.Orders ORDER BY ShipVia, Freight --Checking...
IF (OBJECT_ID('spUpateOrder')IS NOT NULL) DROP PROCEDURE spUpateOrder;
GO
CREATE PROCEDURE spUpateOrder
 @CustomerID nchar(5)
,@EmployeeID [int]
,@OrderDate datetime = NULL
,@RequiredDate datetime = NULL
,@ShippedDate datetime = NULL
,@ShipVia int = 1  -- may have a primary shipper
,@Freight money
,@ShipName nvarchar(40) = NULL
,@ShipAddress nvarchar(60) = NULL
,@ShipCity nvarchar(15) = NULL
,@ShipRegion nvarchar(15) = NULL
,@ShipPostalCode nvarchar(10) = NULL
,@ShipCountry nvarchar(15) = NULL
AS

DECLARE UpdateOneRowCur CURSOR LOCAL FOR

SELECT Freight FROM [NorthWind].[dbo].[Orders] -- WHERE Freight = NULL
WHERE CustomerID = 'alfki' AND Freight < 30.00 AND Freight IS NOT NULL
SET @Freight = @Freight + .1
OPEN UpdateOneRowCur

FETCH NEXT FROM UpdateOneRowCur INTO @Freight
WHILE @@FETCH_STATUS = 0 
BEGIN
    EXEC spUpateOrder
     @CustomerID
    ,@EmployeeID 
    ,@OrderDate 
    ,@RequiredDate 
    ,@ShippedDate 
    ,@ShipVia  --= 1,  -- may have a primary shipper
    ,@Freight 
    ,@ShipName 
    ,@ShipAddress 
    ,@ShipCity 
    ,@ShipRegion 
    ,@ShipPostalCode 
    ,@ShipCountry 
    FETCH NEXT FROM UpdateOneRowCur INTO @Freight


    RETURN @@Identity
    DECLARE @Ret int
    EXECUTE @Ret = @Freight;
    --EXECUTE  @Ret = spUpateOrder --'alfki', 7, '1/1/2013', null, null, 1
                                     , null;
    IF @ret = 0 
        PRINT 'error!';
    ELSE 
        PRINT 'OrderId entered: ' + CAST(@ret as varchar);

    CLOSE UpdateOneRowCur
    DEALLOCATE UpdateOneRowCur
    END;
    GO
    Declare @Ret int
    EXEC  @Ret = spUpateOrder 'alfki', 7, '1/1/2013', null, null, 1, 25.99;

    GO

[/代码]

此代码确实一次更改了所有行,但我只希望它更改它找到的第一行,然后是下次运行存储过程时找到的第二行。不知道怎么做?注意:为了测试它,我制作了一些具有相同运费值25.99的新行。

答案:

以下是我每次执行存储过程时只更改一行的操作:(这确实很有用!)

 [code]
 --============== UPdate only one row ===============--

 CREATE PROCEDURE uspUpdateOrder
 @Freight money --Testing.

 AS
 /*
 Created by: Chris Singleton
 02/26/2017
 Updates each row that has 25.99 where the customer's name is 'alfki'. 
 */
 BEGIN
    --DECLARE @Freight

    UPDATE top (1) Northwind.dbo.Orders 
    SET Freight = @Freight + .1 
    WHERE CustomerID = 'alfki' AND Freight = 25.99

  END;

  --============ Call the Stored Procedure =============--
 GO
 -- the call:
 Declare @Ret int

 EXEC  @Ret = uspUpdateOrder 25.99;
 If @ret = 0 
   print 'error!';
 else 
    print 'OrderId entered: ' + cast(@ret as varchar);

 DROP PROCEDURE uspUpdateOrder
 GO
 SELECT * FROM [Northwind].[dbo].[Orders] WHERE CustomerID = 'alfki'

 --====================================--
 [/code]

2 个答案:

答案 0 :(得分:1)

您的代码中存在多个问题:

  1. 您正在传递&#39; @ Freight&#39;作为参数。在您的示例中,您要为此变量
  2. 指定值25.99
  3. 然后将变量的值增加0.1(SET @Freight = @Freight + .1)。因此,在您的示例中,变量的值将为26.09
  4. 然后运行查询并用查询结果覆盖@Freight的值(FETCH NEXT FROM UpdateOneRowCur INTO @Freight)。此时,步骤1和2完全是多余的,因为您要覆盖之前的内容。
  5. 您正在使用循环并在循环中继续从查询的结果集中读取一行并覆盖@Freigh的值并调用更新过程。
  6. 如果您只需要更新第一行,那么您可以写下:

    SELECT top 1 @Freight = Freight FROM [NorthWind].[dbo].[Orders] -- WHERE Freight = NULL
    WHERE CustomerID = 'alfki' AND Freight < 30.00 AND Freight IS NOT NULL
    SET @Freight = @Freight + .1   -- I'm not sure if you realy want to do this or not
    

    我在您的查询中所做的更改是我只返回一行(select top 1)并同时指定值@Freight

    你真的不需要任何光标或循环。

答案 1 :(得分:0)

Sparrow在某种程度上是正确的,我不需要光标来编码,所以我给了Sparrow点,但为了专注于带过滤器的一行,你可以做到这一点。

[Code]
--============== UPdate only one row ===============--

CREATE PROCEDURE uspUpdateOrder
@Freight money --Testing.

AS
/*
Created by: Chris Singleton
02/26/2017
Updates each row that has 25.99 where the customer's name is 'alfki'. 
*/
BEGIN
--DECLARE @Freight

UPDATE top (1) Northwind.dbo.Orders 
SET Freight = @Freight + .1 
WHERE CustomerID = 'alfki' AND Freight = 25.99

END;

--============ Call the Stored Procedure =============--
GO
-- the call:
Declare @Ret int

EXEC  @Ret = uspUpdateOrder 25.99;
If @ret = 0 
print 'error!';
else 
print 'OrderId entered: ' + cast(@ret as varchar);

DROP PROCEDURE uspUpdateOrder
GO
SELECT * FROM [Northwind].[dbo].[Orders] WHERE CustomerID = 'alfki'

--====================================--

[/Code]

注意:您可以使用update子句TOP(1)和where子句的组合作为过滤器来关注行。这项工作很好!