database_scoped_configurations 中的錯誤
我正在嘗試從以下位置插入結果集:
SELECT * FROM sys.database_scoped_configurations
進入臨時表,因為我想檢查伺服器上所有數據庫的設置。所以我寫了這段程式碼:
DROP TABLE IF EXISTS #h CREATE TABLE #h(dbname sysname, configuration_id INT, name sysname, value SQL_VARIANT, value_for_secondary SQL_VARIANT) EXEC sys.sp_MSforeachdb 'USE ?; insert into #h(dbname, configuration_id, name, value,value_for_secondary) SELECT ''?'' as dbname, * FROM sys.database_scoped_configurations D' SELECT * FROM #h H
但是每個數據庫只有一行,而不是我期望在每個數據庫中執行普通選擇的四行**。**
我知道有比使用 sp_MSForEachDB 更好的編碼方法,我嘗試了幾種。但我仍然每個數據庫只能得到一行。我在 SQL Server 2016 RTM 和 SP1 上都試過了
這是 SQL Server 2016 的錯誤,還是我做錯了什麼?
這是 SQL Server 2016 的錯誤嗎?
是的。這絕對不是正確的行為。我已在此處報告並已在 SQL Server 2016 SP2 CU9 中修復。
正如Mikael Eriksson在評論中所說,
sys.database_scoped_configurations
並sys.dm_exec_sessions
以格式的視圖實現SELECT ... FROM OpenRowset(TABLE xxxx)
但是比較下面的兩個計劃有一個明顯的區別。
DBCC TRACEON(3604); DECLARE @database_scoped_configurations TABLE(x INT); INSERT INTO @database_scoped_configurations SELECT configuration_id FROM sys.database_scoped_configurations OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 ); DECLARE @dm_exec_sessions TABLE(x INT); INSERT INTO @dm_exec_sessions SELECT session_id FROM sys.dm_exec_sessions OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 );
這兩個查詢的跟踪標誌 8619 輸出顯示
應用規則:EnforceHPandAccCard - x0-> Spool or Top (x0)
SQL Server 顯然無法確定 TVF 的源不是插入目標,因此它需要萬聖節保護。
在會話案例中,這被實現為首先擷取所有行的假離線。在計劃中
database_scoped_configurations
添加一個TOP 1
。本文討論了TOP
萬聖節保護的使用。該文章還提到了一個未記錄的跟踪標誌來強制使用假離線而不是按預期工作。TOP
DECLARE @database_scoped_configurations TABLE(x INT); INSERT INTO @database_scoped_configurations SELECT configuration_id FROM sys.database_scoped_configurations OPTION (QUERYTRACEON 8692)
使用
TOP 1
而不是假離線的一個明顯問題是它會任意限制插入的行數。所以這只有在函式返回的行數 <=1 時才有效。最初的備忘錄是這樣的
將此與查詢 2 的初始備忘錄進行比較
如果我正確理解上述內容,它認為第一個 TVF 最多可以返回一行,因此應用了不正確的優化。第二個查詢的 Max 設置為
1.34078E+154
(2^512
)。我不知道這個最大行數是從哪裡得出的。也許是 DMV 的作者提供的元數據?
TOP(50)
解決方法沒有被重寫也很奇怪,TOP(1)
因為TOP(50)
不會阻止萬聖節問題的發生(儘管會無限期地阻止它繼續)