Cursorfetch:INTO列表中声明的变量数必须与所选列的变量数相匹配

时间:2011-01-23 22:47:21

标签: asp.net sql sql-server-2005

我有以下存储过程,如果我在我们的SQL分析器上执行它,它会返回记录没有问题。但是,如果我通过ASP.NET(我正在使用EntitySpace对象)执行此操作以将此查询生成到数据表中,并且它说:“Cursorfetch:在INTO列表中声明的变量数必须与所选列的变量数匹配。”

我和EntitySpace团队讨论了这个问题,他们说这是查询问题吗?!?!有什么想法吗?我们坚持这个问题以及任何有益的指导或提示。

我们使用的环境: .NET 4 EntitySpace 2010 SQL Server 2005数据库

ALTER PROCEDURE [dbo].[rpt_CPRRespondListReport]
(
@SurveyID INT
)
AS
BEGIN
SET NOCOUNT ON;
SET FMTONLY OFF;

DECLARE @SID INT;

SELECT @SID = sid 
FROM lime_Surveys
WHERE sid = @SurveyID

IF (@SID > 1)
BEGIN

    DECLARE @T TABLE
    (
        RecID INT,
        RecID2 INT,
        RecID3 INT,
        RecID4 INT,
        FirstName VARCHAR(40),
        LastName VARCHAR(40),
        Email VARCHAR(320),
        QuestionName VARCHAR(100),
        QuestionValue1 VARCHAR(5),
        QuestionValue2 VARCHAR(5),
        QuestionValue3 VARCHAR(1000),
        QuestionValue4 VARCHAR(5)
    );

    DECLARE @ColumnNameRow VARCHAR(MAX);
    DECLARE @Column_name VARCHAR(32);

    DECLARE @sqlstatement1 NVARCHAR(MAX) 
    SET @sqlstatement1 = 'DECLARE  QuestionCursor CURSOR FOR ' +    
                            'SELECT column_name ' +
                            'FROM information_schema.columns (NOLOCK) ' +
                            'WHERE table_name = ''lime_survey_' + CAST(@SurveyID AS VARCHAR) + ''' AND Ordinal_position >= 10 ' +
                            'ORDER BY ordinal_position ASC'

    EXEC sp_executesql @sqlstatement1

    SET @ColumnNameRow = '';

    OPEN QuestionCursor
    FETCH NEXT FROM QuestionCursor
    INTO @Column_name

    WHILE @@FETCH_STATUS = 0
    BEGIN       
        SET @ColumnNameRow = @ColumnNameRow + '[' + @Column_Name + ']' + ', ' 

        FETCH NEXT 
        FROM QuestionCursor 
        INTO    @Column_name
    END

    SET @ColumnNameRow = SUBSTRING(@ColumnNameRow, 1, LEN(@ColumnNameRow) - 1); 

    CLOSE QuestionCursor
    DEALLOCATE QuestionCursor

    DECLARE @tid INT;
    DECLARE @FirstName VARCHAR(40);
    DECLARE @LastName VARCHAR(40);
    DECLARE @Email VARCHAR(320);
    DECLARE @Q010101 VARCHAR(5);
    DECLARE @Q010102 VARCHAR(5);
    DECLARE @Q010103 VARCHAR(1000);
    DECLARE @Q010201 VARCHAR(5);
    DECLARE @Q010202 VARCHAR(5);
    DECLARE @Q010203 VARCHAR(1000);
    DECLARE @Q010301 VARCHAR(5);
    DECLARE @Q010302 VARCHAR(5);
    DECLARE @Q010303 VARCHAR(1000);
    DECLARE @Q010401 VARCHAR(5);
    DECLARE @Q010402 VARCHAR(5);
    DECLARE @Q010403 VARCHAR(1000);
    DECLARE @Q010501 VARCHAR(5);
    DECLARE @Q010502 VARCHAR(5);
    DECLARE @Q010503 VARCHAR(1000);
    DECLARE @Q010601 VARCHAR(5);
    DECLARE @Q010602 VARCHAR(5);
    DECLARE @Q010603 VARCHAR(1000);
    DECLARE @Q010701 VARCHAR(5);
    DECLARE @Q010702 VARCHAR(5);
    DECLARE @Q010703 VARCHAR(1000);
    DECLARE @Q010801 VARCHAR(5);
    DECLARE @Q010802 VARCHAR(5);
    DECLARE @Q010803 VARCHAR(1000);
    DECLARE @Q010901 VARCHAR(5);
    DECLARE @Q010902 VARCHAR(5);
    DECLARE @Q010903 VARCHAR(1000);
    DECLARE @Q011001 VARCHAR(5);
    DECLARE @Q011002 VARCHAR(5);
    DECLARE @Q011003 VARCHAR(1000);
    DECLARE @Q011101 VARCHAR(5);
    DECLARE @Q011102 VARCHAR(5);
    DECLARE @Q011103 VARCHAR(1000);
    DECLARE @Q011201 VARCHAR(5);
    DECLARE @Q011202 VARCHAR(5);
    DECLARE @Q011203 VARCHAR(1000);
    DECLARE @Q011301 VARCHAR(5);
    DECLARE @Q011303 VARCHAR(1000);


    DECLARE @sqlstatement2 NVARCHAR(MAX) 
    SET @sqlstatement2 = 'DECLARE  SURVEY_RESULT_CURSOR CURSOR FOR  
                            SELECT tid, FirstName, LastName, Email, ' + @ColumnNameRow + '
                            FROM dbo.lime_tokens_' + CAST(@SurveyID AS VARCHAR)  + ' a (NOLOCK) INNER JOIN lime_survey_' + CAST(@SurveyID AS VARCHAR)  + ' b (NOLOCK) ON a.token = b.token
                            where Completed IS NOT NULL'

    EXEC sp_executesql @sqlstatement2 

    OPEN SURVEY_RESULT_CURSOR
    FETCH NEXT FROM SURVEY_RESULT_CURSOR
    INTO @tid, @FirstName, @LastName, @Email, 
         @Q010101, @Q010102, @Q010103, @Q010201, @Q010202, @Q010203, @Q010301, @Q010302, @Q010303, @Q010401, @Q010402, @Q010403,
         @Q010501, @Q010502, @Q010503, @Q010601, @Q010602, @Q010603, @Q010701, @Q010702, @Q010703, @Q010801, @Q010802, @Q010803,
         @Q010901, @Q010902, @Q010903, @Q011001, @Q011002, @Q011003, @Q011101, @Q011102, @Q011103, @Q011201, @Q011202, @Q011203,
         @Q011301, @Q011303 

    WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO @T(RecID, RecID2, RecID3, RecID4, FirstName, LastName, Email, QuestionName, QuestionValue1, QuestionValue2, QuestionValue3) 
        SELECT @tid, 1, 1, 1, @FirstName, @LastName, @Email, 'Mobile Voice Coverage', @Q010101, @Q010102, @Q010103  
        UNION
        SELECT @tid, 1, 2, 1, @FirstName, @LastName, @Email, 'Mobile Data Coverage', @Q010201, @Q010202, @Q010203 
        UNION
        SELECT @tid, 1, 3, 1, @FirstName, @LastName, @Email, 'Mobile Voice Costs', @Q010301, @Q010302, @Q010303 
        UNION
        SELECT @tid, 1, 4, 1, @FirstName, @LastName, @Email, 'Mobile Data Costs', @Q010401, @Q010402, @Q010403 
        UNION
        SELECT @tid, 1, 5, 1, @FirstName, @LastName, @Email, 'International Roaming Costs', @Q010501, @Q010502, @Q010503  
        UNION
        SELECT @tid, 1, 6, 1, @FirstName, @LastName, @Email, 'Handset Quality', @Q010601, @Q010602, @Q010603 
        UNION
        SELECT @tid, 1, 7, 1, @FirstName, @LastName, @Email, 'Mobile Capped Plans', @Q010701, @Q010702, @Q010703 
        UNION
        SELECT @tid, 1, 8, 1, @FirstName, @LastName, @Email, 'Message Bank / Voicemail', @Q010801, @Q010802, @Q010803
        UNION
        SELECT @tid, 1, 9, 1, @FirstName, @LastName, @Email, 'SMS', @Q010901, @Q010902, @Q010903
        UNION
        SELECT @tid, 1, 10, 1, @FirstName, @LastName, @Email, 'Mobile Internet / Email Account', @Q011001, @Q011002, @Q011003
        UNION
        SELECT @tid, 1, 11, 1, @FirstName, @LastName, @Email, 'Access to our office intranet', @Q011101, @Q011102, @Q011103
        UNION
        SELECT @tid, 1, 12, 1, @FirstName, @LastName, @Email, 'Account Management', @Q011201, @Q011202, @Q011203
        UNION
        SELECT @tid, 1, 13, 3, @FirstName, @LastName, @Email, 'Current Provider', @Q011301, null, @Q011303

    FETCH NEXT FROM SURVEY_RESULT_CURSOR
    INTO @tid, @FirstName, @LastName, @Email, 
         @Q010101, @Q010102, @Q010103, @Q010201, @Q010202, @Q010203, @Q010301, @Q010302, @Q010303, @Q010401, @Q010402, @Q010403,
         @Q010501, @Q010502, @Q010503, @Q010601, @Q010602, @Q010603, @Q010701, @Q010702, @Q010703, @Q010801, @Q010802, @Q010803,
         @Q010901, @Q010902, @Q010903, @Q011001, @Q011002, @Q011003, @Q011101, @Q011102, @Q011103, @Q011201, @Q011202, @Q011203,
         @Q011301, @Q011303  

    END
    CLOSE SURVEY_RESULT_CURSOR
    DEALLOCATE SURVEY_RESULT_CURSOR

    SELECT RecID, RecID2, RecID3, RecID4, FirstName, LastName, Email, QuestionName, b.Title AS QuestionValue1, 
            b2.Title AS QuestionValue2, QuestionValue3
    FROM @T a LEFT OUTER JOIN lime_labels b (NOLOCK) ON a.QuestionValue1 = b.Code
            LEFT OUTER JOIN lime_labels b2 (NOLOCK) ON a.QuestionValue2 = b2.Code
    ORDER BY RecID ASC, RecID2 ASC, RecID3 ASC

END
END

1 个答案:

答案 0 :(得分:2)

你的问题在于光标SURVEY_RESULT_CURSOR是用可变数量的列定义的

'DECLARE  SURVEY_RESULT_CURSOR CURSOR FOR  
 SELECT tid, FirstName, LastName, Email, ' + @ColumnNameRow + '

而FETCH .. INTO子句有一个要插入

的FIXED列列表
FETCH NEXT FROM SURVEY_RESULT_CURSOR
INTO @tid, @FirstName, @LastName, @Email, 
     @Q010101, @Q010102, @Q010103, @Q010201, @Q010202, @Q010203, @Q010301, @Q010302, @Q010303, @Q010401, @Q010402, @Q010403,
     @Q010501, @Q010502, @Q010503, @Q010601, @Q010602, @Q010603, @Q010701, @Q010702, @Q010703, @Q010801, @Q010802, @Q010803,
     @Q010901, @Q010902, @Q010903, @Q011001, @Q011002, @Q011003, @Q011101, @Q011102, @Q011103, @Q011201, @Q011202, @Q011203,
     @Q011301, @Q011303 

当这两个计数不匹配时,您将收到该错误。

考虑它是否应该是静态计数(甚至不需要QuestionCursor)或重新考虑你的方法(可能是动态SQL)

编辑:在两个条件下,您仍然可以将抓取到SURVEY_RESULT_CURSOR修复的变量列表中

  1. 变量列表等于或大于每次使用的最大列数
  2. 生成时变量@ColumnNameRow填充为完整列数。
  3. 对于2,不难计算有多少逗号(假设列名没有逗号),然后根据需要追加cast(NULL as varchar(5)) dummcol1, ..个。 varchar(5)到varvar的@var(1000)就可以了。

    计算逗号:

    set @commacount = len(@ColumnNameRow) - len(replace(@ColumnNameRow,',',''))