Sql-Server

如何查找儲存過程和表之間的類型不匹配(隱式轉換)?

  • October 7, 2021

我有一個包含這些行的儲存過程

DECLARE @newTimestamp datetime = CURRENT_TIMESTAMP
UPDATE  dbo.Accounts
SET     Modified = @newTimestamp

但是,在 Accounts DB 中,我們有這個

[Modified]         DATETIME2 (7) NOT NULL,

然後每當我們進行比較(特別是平等)時,我們都沒有得到想要的答案。我們已經通過將兼容性級別設置得足夠低(110)來解決這個問題,但是有沒有簡單的方法可以找到我們的儲存過程與表中的數據類型不匹配的任何實例?

我寧願不必編寫解析器,但似乎如果必須,我會遍歷每個表定義並記錄列類型,然後找到每列的每次使用並嘗試確定它是否被設置或與聲明為不同類型的變數相比。

是否有任何工具已經可以做到這一點,或者係統視圖或日誌中的某處是否存在投訴?

我發現 Brent Ozar 的 sp_blitzcache 可能會在查詢計劃中找到它,但不能保證記憶體將具有給定數據庫的每個實例;我認為對程式碼進行靜態分析而不是實時查看正在執行的 SQL 伺服器會讓我感覺更舒服。我可以訪問(許多)數據庫的實時副本,以及 Visual Studio 中 SQL 解決方案的原始碼。

編輯 - 與我的問題無關,但我可以提供背景。當我們有一個日期時間時,它在小數點後有 3 位精度。當我們有一個 datetime2 時,它有 7 位精度。如果您採用單個時間戳,並嘗試比較同一時刻的日期時間和日期時間2,它們將不相等。

如果我們將兼容性級別固定為 110,它會忽略 datetime2 的額外準確性,這是我們目前的行為。

您可以使用 DMV 查看查詢計劃記憶體,並在計劃的 XML 上使用 XQuery 過濾隱式轉換

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
 cplan.usecounts,
 cplan.objtype,
 qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
WHERE qplan.query_plan.exist('//Convert[@Implicit="1"]') = 1;

您可以對 Query Store 執行相同的操作,這將在服務重新啟動之間保留計劃。

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
 v.query_plan
FROM sys.query_store_plan AS cplan
CROSS APPLY (VALUES(CAST(query_plan AS xml))) v(query_plan)
WHERE v.query_plan.exist('//Convert[@Implicit="1"]') = 1;

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