SQL Server中游标的用途是什么?

时间:2010-11-19 07:08:05

标签: sql-server database-cursor

我想使用数据库游标;首先,我需要了解它的用途和语法是什么,以及在哪种情况下我们可以在存储过程中使用它?不同版本的SQL Server是否有不同的语法?

什么时候需要使用?

7 个答案:

答案 0 :(得分:37)

游标是一种通过结果集的行显式枚举的机制,而不是像这样检索它。

然而,尽管习惯于编写While Not RS.EOF Do ...的程序员使用它们可能会更舒服,但如果可能的话,它们通常是SQL Server存储过程中应该避免的 - 如果你可以在没有编写查询的情况下编写查询使用游标,您可以为优化器找到一种快速实现它的方法。

老实说,我从来没有找到一个无法避免的游标的实际用例,除了一些管理任务,例如循环遍历目录中的所有索引并重建它们。我认为它们可能在报告生成或邮件合并中有一些用途,但在与数据库对话的应用程序中执行类似游标的工作可能更有效,让数据库引擎做它最擅长的操作 - 设置操作。 / p>

答案 1 :(得分:16)

  使用

游标,因为在子查询中我们可以逐行获取记录   所以我们使用游标来获取记录

游标示例:

DECLARE @eName varchar(50), @job varchar(50)

DECLARE MynewCursor CURSOR -- Declare cursor name

FOR
Select eName, job FROM emp where deptno =10

OPEN MynewCursor -- open the cursor

FETCH NEXT FROM MynewCursor
INTO @eName, @job

PRINT @eName + ' ' + @job -- print the name

WHILE @@FETCH_STATUS = 0

BEGIN

FETCH NEXT FROM MynewCursor 
INTO @ename, @job

PRINT @eName +' ' + @job -- print the name

END

CLOSE MynewCursor

DEALLOCATE MynewCursor

<强>输出:

ROHIT                           PRG  
jayesh                          PRG
Rocky                           prg
Rocky                           prg

答案 2 :(得分:8)

游标可能用于逐行检索数据。它的作用类似于循环语句(即while或for循环)。 要在SQL过程中使用游标,您需要执行以下操作: 1.Declare定义结果集的游标。 2.打开光标以建立结果集。 3.根据需要从光标获取数据到局部变量,一次一行。 4.完成后关闭光标。

代表:

declare @tab table
(
Game varchar(15),
Rollno varchar(15)
)
insert into @tab values('Cricket','R11')
insert into @tab values('VollyBall','R12')

declare @game  varchar(20)
declare @Rollno varchar(20)

declare cur2 cursor for select game,rollno from @tab 

open cur2

fetch next from cur2 into @game,@rollno

WHILE   @@FETCH_STATUS = 0   
begin

print @game

print @rollno

FETCH NEXT FROM cur2 into @game,@rollno

end

close cur2

deallocate cur2

答案 3 :(得分:1)

我认为,如果要对返回集的不同行上的特征进行比较,或者在某些情况下要编写与标准行不同的输出行格式,则可能需要使用游标。想到两个例子:

  1. 一个人在大学里,每个课程的每个添加和删除都有自己的行。它可能是糟糕的设计,但您需要比较各行以了解您有多少个添加和删除行,以确定该人是否在该类中。我不能想到只用sql做这件事的直接方法。

  2. 另一个例子是为GL期刊撰写期刊总计。您在日记帐中获得了任意数量的借记和贷记,您在行集中返回了许多日记帐,并且每次完成日记帐时都要编写日记帐总计,以将其发布到总帐中。使用光标,您可以判断何时离开一个日记帐并启动另一个日记帐并为您的借方和贷记设置累加器,并编写与借记/贷记行不同的日记帐总计行(或表格插入)。

答案 4 :(得分:1)

光标本身是一个迭代器(如WHILE)。说迭​​代器是指遍历记录集(也就是一组选定的数据行)并在遍历时对其进行操作的方法。例如,操作可以是INSERT或DELETE。因此,例如,您可以将其用于数据检索。游标按顺序处理结果集的行-逐行。游标可以看作是指向一组行中的一行的指针,一次只能引用一行,但是可以根据需要移动到结果集的其他行。

link可以清楚地说明其语法,并包含其他信息和示例。

游标也可以在Sprocs中使用。它们是一种快捷方式,使您可以使用一个查询而不是多个查询来执行任务。但是,游标会识别作用域,并且在存储过程的作用域之外被认为是未定义的,并且它们的操作在单个过程中执行。存储过程无法打开,获取或关闭过程中未声明的游标。

答案 5 :(得分:0)

在SQL Server中,在需要时使用游标,而不是一次在结果集中的所有行上操作的T-SQL命令,而是在需要更新数据库表中的记录时使用游标以单例方式,换句话说,一行一行地一次或一行一行地获取一行。

使用游标包括几个步骤:

声明-声明用于定义新的游标。 打开-通过执行游标定义的SQL语句来打开并填充游标。 提取-打开游标时,可以从游标中一一检索行。 关闭-进行数据操作后,我们应显式关闭游标。 取消分配-最后,我们需要删除游标定义并释放与游标关联的所有系统资源。 语法

DECLARE cursor_name CURSOR [本地| GLOBAL] [FORWARD_ONLY |滚动] [静态|按键集|动态| FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS |最佳] [TYPE_WARNING] FOR select_statement [FOR UPDATE [OF column_name [,... n]]] [;]

答案 6 :(得分:0)

CREATE PROCEDURE [dbo].[SP_Data_newUsingCursor]
(
    @SCode NVARCHAR(MAX)=NULL,
    @Month INT=NULL,
    @Year INT=NULL,
    @Msg NVARCHAR(MAX)=null OUTPUT
)
AS

BEGIN
 
    DECLARE @SEPERATOR as VARCHAR(1)
    DECLARE @SP INT
    DECLARE @VALUE VARCHAR(MAX)
    SET @SEPERATOR = ','
    
    CREATE TABLE #TempSiteCode (id int NOT NULL)
    
    WHILE PATINDEX('%' + @SEPERATOR + '%', @SCode ) <> 0 
        BEGIN
                SELECT  @SP = PATINDEX('%' + @SEPERATOR + '%' ,@SCode)
                SELECT  @VALUE = LEFT(@SCode , @SP - 1)
                SELECT  @SCode = STUFF(@SCode, 1, @SP, '')  
                INSERT INTO #TempSiteCode (id) VALUES (@VALUE)
        END


DECLARE 
@EmpCode bigint=null,
@EmpName nvarchar(50)=null

CREATE TABLE #TempEmpDetail
(
    EmpCode bigint
)


CREATE TABLE #TempFinalDetail
(   
    EmpCode bigint,
    EmpName nvarchar(500)
    
    
)


DECLARE @TempSCursor CURSOR
DECLARE @TempFinalCursor CURSOR



INSERT INTO #TempEmpDetail
(
    EmpCode
)
(

SELECT DISTINCT EmpCode FRom tbl_Att_MSCode
WHERE tbl_Att_MSCode.SiteCode IN (SELECT id FROM #TempSiteCode)
AND fldMonth=@Month AND fldYear=@Year

)

SET @TempSiteFinalCursor=CURSOR FOR SELECT EmpCode FROM #TempEmpDetail
OPEN @TempSiteFinalCursor
FETCH NEXT FROM @TempSiteFinalCursor INTO @EmpCode,@SiteCode,@HrdCompanyId

WHILE @@FETCH_STATUS=0
    BEGIN
        
        SEt @EmpName=(SELECt EmpName FROm tbl_Employees WHERE EmpCode=@EmpCode)

        INSERT INTO #TempFinalDetail
        (       
            EmpCode,
            EmpName
        )

        VALUES
        (
         
          @EmpCode,
          @EmpName
         )


         FETCH NEXT FROM @TempSiteFinalCursor INTO @EmpCode
    END


    SELECT  EmpCode,
            EmpName
            FROM #TempFinalDetail


DEALLOCATE @TempSiteFinalCursor

DROP TABLE #TempEmpDetail
DROP TABLE #TempFinalDetail

END