36

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

什么时候需要使用?

4

7 回答 7

47

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

然而,虽然对于习惯于编写的程序员来说,使用它们可能更舒服,但如果可能While Not RS.EOF Do ...的话,它们通常是在 SQL Server 存储过程中要避免的事情——如果你可以在不使用游标的情况下编写查询,你给优化器有更好的机会找到实现它的快速方法。

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

于 2010-11-19T07:15:21.507 回答
17

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

光标示例:

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
于 2012-12-11T08:32:59.330 回答
8

游标可用于逐行检索数据。它的作用类似于循环语句(即 while 或 for 循环)。要在 SQL 过程中使用游标,您需要执行以下操作: 1.声明一个定义结果集的游标。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
于 2012-10-04T06:53:07.317 回答
1

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

  1. 一个是在一所大学里,每个班级的添加和删除在表格中都有自己的行。这可能是一个糟糕的设计,但您需要跨行进行比较以了解您有多少添加和删除行,以确定该人是否在课堂上。我想不出只用 sql 就能做到这一点的直接方法。

  2. 另一个例子是为 GL 期刊编写期刊总行。您的日记帐中有任意数量的借方和贷方,您的行集回报中有许多日记帐,并且您希望在每次完成日记帐时写入日记帐总行以将其过帐到总帐中。使用光标,您可以知道您何时离开一个日记帐并开始另一个日记帐,并为您的借方和贷方设置累加器,并编写与借方/贷方行不同的日记帐总行(或表格插入)。

于 2018-01-20T00:00:41.203 回答
1

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

链接可以清楚地解释其语法,并包含附加信息和示例。

游标也可以在 Sprocs 中使用。它们是一种快捷方式,允许您使用一个查询而不是多个查询来完成一项任务。但是,游标识别范围并被视为未定义超出存储过程的范围,并且它们的操作在单个过程中执行。存储过程无法打开、获取或关闭未在过程中声明的游标。

于 2018-07-27T06:14:20.570 回答
0

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

使用游标包括几个步骤:

Declare - Declare 用于定义一个新的游标。打开 - 通过执行游标定义的 SQL 语句来打开和填充游标。Fetch - 当游标打开时,可以从游标中逐一检索行。关闭 - 数据操作后,我们应该明确关闭游标。Deallocate - 最后,我们需要删除游标定义并释放所有与游标相关的系统资源。句法

声明 cursor_name CURSOR [ 本地 | 全球 ] [ FORWARD_ONLY | 滚动 ] [ 静态 | 键盘 | 动态 | FAST_FORWARD ] [ 只读 | 滚动锁定 | OPTIMISTIC ] [ TYPE_WARNING] FOR select_statement [FOR UPDATE [ OF column_name [ ,...n ] ] [;]

于 2019-06-15T13:49:43.067 回答
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
于 2021-04-17T09:05:34.857 回答