Sql-Server-2008

更改游標內的 SET 選項 - 基於兼容性級別的不同行為

  • November 3, 2021

我發現數據庫兼容性級別之間的一段程式碼的行為存在差異,並想知道這是什麼原因。下面是一個簡單的範例,它遍歷一個計數表並ROWCOUNT在第 50 次迭代時更改選項:

設置:

/* Create tally table */

SELECT  TOP 100
       ROW_NUMBER() OVER (ORDER BY a.object_id) AS Number
INTO    #Tally
FROM    sys.objects a
       CROSS JOIN sys.objects b;

/* Create Some databases with different compatibility levels */

CREATE DATABASE [100Compat] WITH COMPATIBILITY_LEVEL = 100
CREATE DATABASE [110Compat] WITH COMPATIBILITY_LEVEL = 110
CREATE DATABASE [120Compat] WITH COMPATIBILITY_LEVEL = 120
CREATE DATABASE [130Compat] WITH COMPATIBILITY_LEVEL = 130

受影響的程式碼:

/* cursor through the tally table */
DECLARE MyCursor CURSOR
FOR
SELECT  Number
FROM    #Tally
FOR READ ONLY;

DECLARE @num INT;

OPEN MyCursor

FETCH MyCursor
INTO @num
WHILE @@FETCH_STATUS = 0

BEGIN
   SET ROWCOUNT 0

   /* change the value for ROWCOUNT on iteration 50 */
   IF @num = 50 SET ROWCOUNT 1

   PRINT @num

   FETCH MyCursor
   INTO @num
END

SET ROWCOUNT 0

CLOSE MyCursor
DEALLOCATE MyCursor

如果我對它執行上述內容,[100Compat]則會在消息視窗中列印數字 1-100。

如果我針對 執行上述操作[110Compat][120Compat]或者[130Compat]我可以在消息視窗中看到值 1-50 和錯誤消息

消息 16958,級別 16,狀態 3,第 41 行無法完成游標操作,因為自聲明游標後設置選項已更改。

導致這種行為變化的兩種兼容模式之間有什麼區別?是否有在 110 中啟用/禁用的跟踪標誌或類似的東西?

我看過這篇文章,但似乎沒有什麼明顯的原因導致差異

SQL Server 2012對 SET ROWCOUNT 進行了重大更改

SET ROWCOUNT 的行為已更改,以提高許多常見查詢的效率,並可能影響兼容級別 110 和更高級別的查詢計劃。當 SET ROWCOUNT 語句在 DECLARE CURSOR 語句之後和 FETCH 語句之前將 ROWCOUNT 值更改為 0 或從 0 時,可能會導致錯誤。要避免此錯誤,請將數據庫兼容級別設置為 100 或在游標語句之外設置 ROWCOUNT。

正如您的重現腳本所展示的,此更改由數據庫兼容性級別控制。ROWCOUNT在聲明游標後更改設置時,兼容級別 110 (SQL 2012) 或更高版本將導致錯誤。

引用自:https://dba.stackexchange.com/questions/302064