sp_Blitz 因整理錯誤而失敗
SQL Server 版本(從選擇 @@VERSION 輸出):Microsoft SQL Server 2017 (RTM-CU19) (KB4535007) - 14.0.3281.6 (X64) (Build 14393: )
sp_Blitz
從 Brent Ozar安裝,儲存過程創建成功。程式碼中的版本資訊:
SELECT @Version = '7.93', @VersionDate = '20200217';
該實例有 4 個帶排序規則的系統
SQL_Latin1_General_CP1_CI_AS
數據庫和 2 個帶排序規則的使用者數據庫SQL_Latin1_General_CP1_CS_AS
當我嘗試執行時,
sp_Blitz
我得到了這個:消息 468,級別 16,狀態 9,程序 sp_Blitz,第 896 行
$$ Batch Start Line 0 $$ 無法解決等於操作中“SQL_Latin1_General_CP1_CS_AS”和“SQL_Latin1_General_CP1_CI_AS”之間的排序規則衝突。
感謝您在故障排除方面的任何幫助(我主要是一個 Oracle 人員,他收到了一個 SQL Server 進行審查,並記住這可能是一個很好的開始,對於顯而易見的事情開始)。
從評論中添加解決方案:儲存過程是在區分大小寫的使用者數據庫中創建的,它試圖將內容複製到區分大小寫的 TempDB 中。
從區分大小寫的使用者數據庫中刪除 sp_Blitz 並將其安裝在 master 中(然後將反映系統數據庫排序規則)後,它工作正常。
不要質疑供應商推薦的用法,但據我所知,在“典型”條件下,sp_Blitz安裝在使用者數據庫中時工作得很好,即使是與實例具有不同排序規則的數據庫。什麼不是“典型的”,以至於會出現排序規則不匹配錯誤?使用包含的數據庫(即“
CONTAINMENT = PARTIAL
”)。發生錯誤是因為在包含的數據庫中,[tempdb]
使用者數據(與[tempdb]
元數據相反)的預設排序規則實際上是包含的 DB 的預設排序規則(類似於表變數的工作方式)。在“典型”條件下,sp_Blitz中的許多查詢包含以下
WHERE
謂詞(d
表別名為 forsys.databases
):AND d.name NOT IN ( SELECT DISTINCT DatabaseName FROM #SkipChecks WHERE CheckID IS NULL OR CheckID = 1)
工作得很好,即使這個儲存過程是使用不同於實例級排序規則的預設排序規則在數據庫中創建的,因為
sys.databases.name
使用實例級排序規則,並且#SkipChecks.DatabaseName
(因為語句中沒有COLLATE
子句CREATE TABLE
)使用預設排序規則of[tempdb]
,其中 99.999% 的時間也是實例級排序規則。重現 OP 收到的錯誤的唯一方法是執行以下操作:
EXEC sp_configure 'contained database authentication', 1; RECONFIGURE; ALTER DATABASE [{user_db_containing_spBlitz}] SET CONTAINMENT = PARTIAL;
假設使用者 DB 的排序規則與實例不同(因此與 不同),那麼在執行sp_Blitz
[tempdb]
時會出現以下錯誤:消息 468,級別 16,狀態 9,過程 dbo.sp_Blitz,第 XXXXX 行
$$ Batch Start Line YYYYY $$
無法解決 equal to 操作中“{contained_db_default_collation}”和“{instance_collation}”之間的排序規則衝突。
同樣,如果供應商(即 Brent)說此儲存過程旨在安裝在 中
[master]
,那麼最好遵循建議。我只是在解釋實際發生的事情,因為它是不明顯的行為。此外,這是另一種真正受益於特殊排序規則名稱的情況,該名稱將動態替換為實例級排序規則。到目前為止,
DATABASE_DEFAULT
這是數據庫的排序規則,無論該排序規則是什麼,都有CATALOG_DEFAULT
旨在幫助包含數據庫的排序規則(儘管在這種情況下它無濟於事),但沒有任何東西代表實例級別。通用腳本,例如sp_Blitz、Ola Hallengren 的數據庫維護腳本等,旨在對整個實例進行操作,並沒有針對特定係統進行編碼,將不可避免地遇到這個問題,並且必須做出不必要的讓步才能使其正常工作。所以,請投票支持我的以下建議來解決這種情況:添加特殊排序規則 INSTANCE_DEFAULT 以像 COLLATE DATABASE_DEFAULT 一樣工作,但使用實例的預設排序規則
如果可以使用創建臨時表
[DatabaseName] sysname COLLATE INSTANCE_DEFAULT
,那麼無論放置什麼數據庫,無論是否包含等,此程式碼都將始終有效。它會正常工作。