【问题标题】:SQL Cursor to Insert into Temporary Table and Fetch From Temparory Table插入临时表并从临时表中获取的 SQL 游标
【发布时间】:2017-09-25 07:29:47
【问题描述】:

先生,

我已经构建了一个 SQL 查询,使用 Cursor 作为 @AllRecords 将值插入临时表,然后从该临时表中获取值。但是当我从表中获取值时,它在最后一条语句中显示错误(错误:@AllRecords 附近的语法不正确)。以下是我的代码:

DECLARE @ColName varchar(20)=null,
        @Query varchar(MAX)=null,
        @DepartmentName varchar(50)=null,
        @deptt_code varchar(4)=null,
        @DistrictId varchar(4)='0001',
        @Deptt_Id char(4)=null,
        @stYear varchar(4)=null, 
        @cYear varchar(4)=null,
        @yr varchar(9)='2017-2018',
        @tno int

BEGIN
        set @stYear = SUBSTRING(@yr,0,5)
        set @cYear = SUBSTRING(@yr,6,4)

--DECLARE & SET COUNTER
DECLARE @counter int
SET @counter = 1

--CREATE DYNAMIC TABLE WITH COLs
DECLARE @AllRecords table
(
  department_name varchar(50),
  project_name varchar(100),
  department_code varchar(4)
 )

--*** Declare Cursor
DECLARE cur_FetchDepartmentName CURSOR READ_ONLY
 FOR 
  select deptt_code,deptt_name+'('+ RTRIM(LTRIM(deptt_short))+')' as dept_name from m_Department 
  where deptt_code in (select distinct department_code from t_Project_Details where district_id=@DistrictId
  and financial_year=@yr)

OPEN cur_FetchDepartmetName

fetch next from cur_FetchDepartmetName into 
@deptt_code, @DepartmentName

--LOOP UNTIL RECORDS ARE AVAILABLE
while @@FETCH_STATUS=0
   BEGIN
      if(@tno=0)
          BEGIN
                set @tno=1
                insert into @AllRecords values(@DepartmentName,@deptt_code)
                fetch next from cur_FetchDepartmetName into
                @deptt_code,@DepartmentName
          END
      else
          BEGIN
                set @tno=@tno+1
                insert into @AllRecords values(@DepartmentName,@deptt_code)
                fetch next from cur_FetchDepartmetName into
                @deptt_code,@DepartmentName
          END

   END
        --CLOSE CURSOR
        CLOSE cur_FetchDepartmetName
        DEALLOCATE cur_FetchDepartmetName

  select department_name, department_code from @AllRecords

【问题讨论】:

  • 在你设置第一个变量的地方,你有BEGIN,它没有关联的END
  • 这必须是不必要使用游标的最好例子。请停下来,深呼吸,然后将其重写为一个简单的 INSERT..SELECT 语句。我会说使用 ROW_NUMBER() 或 IDENTITY() 来获取 @tNo,但我认为没有意义,你不再使用它们了吗?

标签: sql sql-server-2008 cursor


【解决方案1】:

我不想回答这个解决方案中的错误,而是想为这个问题提供一个更好的解决方案。在这个例子中使用游标是完全没有必要的,没有它可以更容易地编写查询。这是一个简单的 INSERT..SELECT 语句,最后可以轻松完成设置 @tno 的记录计数。

BEGIN

set @stYear = SUBSTRING(@yr,0,5);
set @cYear = SUBSTRING(@yr,6,4);

--CREATE DYNAMIC TABLE WITH COLs
DECLARE @AllRecords table
(
  department_name varchar(50),
  project_name varchar(100), --what's the use of this column?
  department_code varchar(4)
 );

INSERT INTO @AllRecords (department_code, department_name)
select deptt_code,deptt_name+'('+ RTRIM(LTRIM(deptt_short))+')' as dept_name from m_Department 
  where deptt_code in (select distinct department_code from t_Project_Details where district_id=@DistrictId
  and financial_year=@yr);


SELECT @tNo = COALESCE(@tno,0) + COUNT(*) FROM @AllRecords;

select department_name, department_code from @AllRecords;

END

请查看这篇关于游标以及如何避免它们的文章:

Cursors and How to Avoid Them

【讨论】:

  • 先生,project_name varchar(100)这个栏目是另一个项目表,它有项目详情,也上传到相应的部门下。
  • 先生,实际上我必须获取每个部门,还要从项目表中获取与该部门对应的项目
  • @SumeetKumar 不管是什么问题,可能都不需要游标
【解决方案2】:

您的 SQL 查询如下:

  BEGIN
         DECLARE @ColName VARCHAR(20)= NULL, @Query VARCHAR(MAX)= NULL, @DepartmentName VARCHAR(50)= NULL, @deptt_code VARCHAR(4)= NULL, @DistrictId VARCHAR(4)= '0001', @Deptt_Id CHAR(4)= NULL, @stYear VARCHAR(4)= NULL, @cYear VARCHAR(4)= NULL, @yr VARCHAR(9)= '2017-2018', @tno INT;
         SET @stYear = SUBSTRING(@yr, 0, 5);
         SET @cYear = SUBSTRING(@yr, 6, 4);

--DECLARE & SET COUNTER
         DECLARE @counter INT;
         SET @counter = 1;

--CREATE DYNAMIC TABLE WITH COLs
         DECLARE @AllRecords TABLE
         (department_name VARCHAR(50),
          project_name    VARCHAR(100),
          department_code VARCHAR(4)
         );

--*** Declare Cursor
         DECLARE cur_FetchDepartmentName CURSOR READ_ONLY
         FOR
             SELECT deptt_code,
                    deptt_name+'('+RTRIM(LTRIM(deptt_short))+')' AS dept_name
             FROM m_Department
             WHERE deptt_code IN
             (
                 SELECT DISTINCT
                        department_code
                 FROM t_Project_Details
                 WHERE district_id = @DistrictId
                       AND financial_year = @yr
             );
         OPEN cur_FetchDepartmetName;
         FETCH NEXT FROM cur_FetchDepartmetName INTO @deptt_code, @DepartmentName;

--LOOP UNTIL RECORDS ARE AVAILABLE
         WHILE @@FETCH_STATUS = 0
             BEGIN
                 IF(@tno = 0)
                     BEGIN
                         SET @tno = 1;
                         INSERT INTO @AllRecords
                         (department_name,
                          department_code
                         )
                                SELECT @DepartmentName,
                                       @deptt_code;
                         FETCH NEXT FROM cur_FetchDepartmetName INTO @deptt_code, @DepartmentName;
                 END;
                     ELSE
                     BEGIN
                         SET @tno = @tno + 1;
                         INSERT INTO @AllRecords
                         (department_name,
                          department_code
                         )
                                SELECT @DepartmentName,
                                       @deptt_code;
                         FETCH NEXT FROM cur_FetchDepartmetName INTO @deptt_code, @DepartmentName;
                 END;
             END;
        --CLOSE CURSOR
         CLOSE cur_FetchDepartmetName;
         DEALLOCATE cur_FetchDepartmetName;

        select department_name, department_code from @AllRecords
     END;

【讨论】:

    最近更新 更多