SQL Server 中的静态游标

SQL Server 的静态游标始终是只读的,因为结果集将存储在 tempdb 中。您可以使用此游标向前和向后移动。

SQL Server 游标场景:通常,关系数据库上的所有操作都作用于一组行。例如,编写 Select 语句会返回满足查询条件的所有记录(结果集)。但是,在某些情况下,我们需要处理单行或少量行块。在这种情况下,我们可以使用游标。

在此游标演示中,我们使用下表,该表包含 14 条记录。

SQL Server 中的游标类型

服务器支持四种类型的游标。

  1. 静态:它显示打开时存在的记录。它不会显示打开后更新、删除或插入的记录。
  2. 仅前进:顾名思义,它只能向前移动,不能向后滚动。这些只读游标按顺序从头到尾获取行。
  3. 键集:这些由键或唯一标识符控制。
  4. 动态:这些与静态相反,并显示打开后由更新、删除或插入所做的更改。
  5. Fast_Forward.

SQL Server 静态游标示例

在此示例中,我们将向您展示如何声明和打开游标。在这里,我们使用的是语法。

DECLARE empCR CURSOR STATIC  
    FOR SELECT * FROM [EmployeeTab]
OPEN empCR  
FETCH NEXT FROM empCR;

分析

在此示例中,以下语句将为 Employee 表中的所有记录声明游标语句。

DECLARE empCR CURSOR STATIC
FOR SELECT * FROM [EmployeeTab]

它将打开声明的 empCR。

OPEN empCR

下一条语句将从中获取一行或返回下一条记录。

FETCH NEXT FROM empCR;

尽管 Employee 表有 14 条记录,但它只检索了一条记录。这是因为 FETCH NEXT 只会从此 SQL Server 游标中获取一行,如果您想要全部获取,请使用循环。

Declare Static Cursor in SQL Server 2

看,它只检索了第二条记录。如果您仔细观察,我们只选择 FETCH 语句,因为我们的 empCR 仍然在使用中,因为我们还没有关闭或取消分配它。

FETCH NEXT FROM Example

让我使用 FETCH LAST 选项。它返回我们表中存在的最后一条记录,即 ID 号 14。

Fetch Next from Static Cursor in SQL Server 4

接下来,我们使用了 FETCH PRIOR 选项。它返回最后一条记录之前的行,即 ID 号 13(14 之前)。

FETCH PRIOR FROM Cursor Example

最后,我们使用了 FETCH FIRST 选项。返回我们表中存在的第一个记录,即 ID 号 1。

FETCH FIRST FROM Cursor Example

SQL Server 游标示例 2

在前面的示例中,我们展示了它如何一次获取(或处理)一行。在此示例中,我们将使用 WHILE LOOP 循环遍历游标元素并将其作为输出打印。

SET NOCOUNT ON
-- Declaring the Variables 
DECLARE @EmpID INT,
        @EmpName VARCHAR(50),
        @EmpEducation VARCHAR(50),
 @EmpOccupation VARCHAR(50),
 @EmpYearlyIncome DECIMAL (10, 2), 
 @EmpSales DECIMAL (10, 2);

DECLARE empCR CURSOR 
STATIC FOR 
 SELECT [ID]
       ,[Name]
       ,[Education]
       ,[Occupation]
       ,[YearlyIncome]
       ,[Sales]
 FROM EmployeeTab

OPEN empCR
IF @@CURSOR_ROWS > 0
BEGIN 
 FETCH NEXT FROM empCR 
                  INTO @EmpID, @EmpName, @EmpEducation,
        @EmpOccupation, @EmpYearlyIncome, @EmpSales
 WHILE @@FETCH_STATUS = 0
 BEGIN
 PRINT 'ID = '+ CONVERT(VARCHAR(10), @EmpID)+', Full Name = '+ @EmpName
 +', Education = '+ @EmpEducation +', Occupation = '+ @EmpOccupation 
 + ', Yearly Income = ' + CONVERT(VARCHAR(10),@EmpYearlyIncome)
 + ', Sales Amount = ' + CONVERT(VARCHAR(10),@EmpSales)
 
                FETCH NEXT FROM empCR 
                              INTO @EmpID, @EmpName, @EmpEducation,
    @EmpOccupation, @EmpYearlyIncome, @EmpSales
 END
END
CLOSE empCR
DEALLOCATE empCR
SET NOCOUNT OFF 

在此示例中,首先,我们使用 SET NOCOUNT ON 来停止 SQL Server 查询中的受影响行数消息。接下来,我们声明了一些变量来保存从中获取的数据。

然后,我们声明并打开了 Employee 表中所有记录的 SQL 游标。

接下来,我们在 IF 语句中使用 @@ 来检查其中是否有任何行。以下语句会将下一条记录获取到已声明的变量中。

FETCH NEXT FROM empCR 
           INTO @EmpID, @EmpName, @EmpEducation,
	       @EmpOccupation, @EmpYearlyIncome, @EmpSales

接下来,我们使用 WHILE LOOP 来循环遍历元素。在循环中,FETCH_STATUS 用于检查 FETCH 语句的状态。在循环中,我们使用 Print 语句逐行打印记录。

PRINT 'ID = '+ CONVERT(VARCHAR(10), @EmpID)+', Full Name = '+ @EmpName
	+', Education = '+ @EmpEducation +', Occupation = '+ @EmpOccupation 
	+ ', Yearly Income = ' + CONVERT(VARCHAR(10),@EmpYearlyIncome)
	+ ', Sales Amount = ' + CONVERT(VARCHAR(10),@EmpSales)

然后,我们使用 FETCH NEXT 从中获取下一条记录。

FETCH NEXT FROM empCR 
           INTO @EmpID, @EmpName, @EmpEducation,
	        @EmpOccupation, @EmpYearlyIncome, @EmpSales

最后,我们使用 CLOSE 和 DEALLOCATE 语句来关闭和取消分配游标。

CLOSE empCR
DEALLOCATE empCR
Fetch Next, Close and Deallocate Statements 7

游标示例 3

在我们之前的 SQL Server 静态游标示例中,我们展示了如何使用 WHILE LOOP 循环遍历元素并将其作为输出打印。在此示例中,我们将在 while 循环内添加一个 select 语句来显示结果集中的项。

SET NOCOUNT ON
DECLARE @EmpID INT,
        @EmpName VARCHAR(50),
        @EmpEducation VARCHAR(50),
	@EmpOccupation VARCHAR(50),
	@EmpYearlyIncome DECIMAL (10, 2), 
	@EmpSales DECIMAL (10, 2);

DECLARE empCR CURSOR 
STATIC FOR 
	SELECT [ID]
	      ,[Name]
	      ,[Education]
	      ,[Occupation]
	      ,[YearlyIncome]
	      ,[Sales]
	FROM EmployeeTab

OPEN empCR
IF @@CURSOR_ROWS > 0
BEGIN 
	FETCH NEXT FROM empCR 
                  INTO @EmpID, @EmpName, @EmpEducation,
		       @EmpOccupation, @EmpYearlyIncome, @EmpSales
	WHILE @@FETCH_STATUS = 0
	BEGIN
		PRINT 'ID = '+ CONVERT(VARCHAR(10), @EmpID)+', Full Name = '+ @EmpName
			+', Education = '+ @EmpEducation +', Occupation = '+ @EmpOccupation 
			+ ', Yearly Income = ' + CONVERT(VARCHAR(10),@EmpYearlyIncome)
			+ ', Sales Amount = ' + CONVERT(VARCHAR(10),@EmpSales)
		
                -- Display the result set
                SELECT @EmpID AS ID, @EmpName AS Name, @EmpEducation AS Education,
		   @EmpOccupation AS Occupation, @EmpYearlyIncome + 25000 AS YearlyIncome, 
                   @EmpSales + 1000 AS Sales
                
                FETCH NEXT FROM empCR 
                              INTO @EmpID, @EmpName, @EmpEducation,
				   @EmpOccupation, @EmpYearlyIncome, @EmpSales
	END
END
CLOSE empCR
DEALLOCATE empCR
SET NOCOUNT OFF 

它将每个记录显示为一个单独的结果集。此外,它还反映了我们在 SELECT Statement 中所做的更改(年收入 + 25000,销售额 + 1000)。

Static Cursor 8

让我们查看 Message 选项卡,检查游标的 Print 语句结果。如您所见,它显示了 Employee 表中的年收入和销售额值。这是因为我们在 Print 语句中没有更改任何值。

Static Cursor 9