我很擅长使用游标。 每次运行存储过程时,我只想让一行更改运费值(不是全部)。任何帮助将不胜感激。
[代码]
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]
答案 0 :(得分:1)
您的代码中存在多个问题:
如果您只需要更新第一行,那么您可以写下:
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子句的组合作为过滤器来关注行。这项工作很好!