T-SQL 存储过程中的游标

T-SQL Cursor in stored procedure

我正在使用存储过程并且我想使用游标来插入新数据(如果数据存在我想更新)

ALTER Procedure [dbo].[conn]
    @ResellerID int,
    @GWResellerID int,
    @UserName varchar(50),
    @Password varchar(50),
    @URL varchar(100),
    @ServiceType int,
    @ServiceDesc varchar(50),
    @FeedFrom bit,
    @PublicKey varchar(max)
AS
    declare gateway cursor for
         select * 
         from reseller_profiles 
         where main_reseller_ID = @ResellerID

    OPEN gateway

    FETCH NEXT FROM gateway INTO @ResellerID

    WHILE @@FETCH_STATUS = 0
    BEGIN
       INSERT INTO [dbo].tblGatewayConnection([ResellerID],[GWResellerID], [UserName], [Password], [URL], [ServiceType], [ServiceDesc],[feedFromMain], publicKey)
       VALUES (@ResellerID, @GWResellerID, @UserName, @Password, @URL, @ServiceType, @ServiceDesc, @FeedFrom, @PublicKey)

       FETCH NEXT FROM gateway INTO @ResellerID
    END

    CLOSE gateway
    DEALLOCATE gateway

我的 table 名字是 tblGatewayConnection 有这些列:

resellerID
gwResellerID
userName
password
url
serviceType
serviceDesc
feedFromMain
publicKey

当我使用存储过程插入数据时,出现异常

Cursorfetch: The number of variables declared in the INTO list must match that of selected columns.

我错过了什么?

我们将不胜感激。

谢谢。

为什么还要用光标呢?!?!?!?!?我不会告诉您光标出了什么问题 - 因为与其修复光标,您应该首先学习避免它

认真 - 避免 RBAR(逐行痛苦)尽可能处理,在这里,它真的毫无意义使用游标 - 只需使用这个干净整洁的 set-based 语句:

ALTER PROCEDURE [dbo].[conn] @ResellerID   INT,
                             @GWResellerID INT,
                             @UserName     VARCHAR(50),
                             @Password     VARCHAR(50),
                             @URL          VARCHAR(100),
                             @ServiceType  INT,
                             @ServiceDesc  VARCHAR(50),
                             @FeedFrom     BIT,
                             @PublicKey    VARCHAR(max)
AS
    INSERT INTO dbo.tblGatewayConnection
                (ResellerID, GWResellerID, UserName, Password,
                 URL, ServiceType, ServiceDesc, feedFromMain,
                 publicKey)
       SELECT 
          ResellerID, GWResellerID, UserName, Password,
          URL, ServiceType, ServiceDesc, feedFromMain,
          publicKey
       FROM   
          dbo.reseller_profiles
       WHERE  
          main_reseller_ID = @ResellerID 

大功告成!!没有凌乱的游标,没有不必要的局部变量 - 只是一个简单的 INSERT ... SELECT,你已经实现了你想要的!

我不确定错误消息是否更容易解释:

Cursorfetch: The number of variables declared in the INTO list must match that of selected columns.

您正在 selecting 所有 来自 reseller_profiles

的列
declare gateway cursor for
     select * 
     from reseller_profiles 
     where main_reseller_ID = @ResellerID

并尝试将它们放入单个变量中:

FETCH NEXT FROM gateway INTO @ResellerID

您 select 在光标中的列数必须与您要插入的变量数相匹配,因此您需要

declare gateway cursor for
     select reseller_id
     from reseller_profiles 
     where main_reseller_ID = @ResellerID

但是 你不应该为此使用游标,你可以使用相同的东西 INSERT .. SELECT:

INSERT INTO [dbo].tblGatewayConnection
(   [ResellerID],[GWResellerID], [UserName], [Password], [URL], 
    [ServiceType], [ServiceDesc],[feedFromMain], publicKey
)
SELECT  Resellerid, @GWResellerID, @UserName, @Password, 
        @URL, @ServiceType, @ServiceDesc, @FeedFrom, @PublicKey
FROM    reseller_profiles 
WHERE   main_reseller_ID = @ResellerID;

如前所述,您应该不惜一切代价避免游标,如果您绝对必须使用游标,请尽可能声明最轻量级的游标。例如,在您的情况下,您只是在游标内向前移动,只读取数据,不修改数据,并且只在本地访问游标,因此您可以按如下方式声明游标:

DECLARE gateway CURSOR LOCAL STATIC FAST_FORWARD
FOR
    SELECT  ...
    FROM ..

虽然游标在最好的时候表现得非常糟糕,但懒惰的声明给它们带来了更糟糕的声誉。

最后,You should get out of the habit of using SELECT *