Sql-Server-2008
更改游標內的 SET 選項 - 基於兼容性級別的不同行為
我發現數據庫兼容性級別之間的一段程式碼的行為存在差異,並想知道這是什麼原因。下面是一個簡單的範例,它遍歷一個計數表並
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) 或更高版本將導致錯誤。