Sql-Server
不正確的唯一標識符在沒有主鍵的情況下工作,但在主鍵下失敗
uniqueidentifier
因此,我們最近對以 a作為主鍵的表的插入執行了一些邏輯測試。這是我的測試查詢;IF OBJECT_ID('tempdb..#DatabaseTable') IS NOT NULL DROP TABLE #DatabaseTable CREATE TABLE #DatabaseTable ([ID] [uniqueidentifier] NOT NULL PRIMARY KEY, [LastUpdate] [datetime] NOT NULL, [Locked] [tinyint] NOT NULL) IF OBJECT_ID('tempdb..#temptable') IS NOT NULL DROP TABLE #temptable CREATE TABLE #temptable (ID varchar(36), Data nvarchar(max)) INSERT INTO #temptable (ID, Data) VALUES ('g078f19e-e150-4bb9-b5f4-b20b3fc64016', 'text goes here') SELECT tmp.ID ,tmp.Data FROM #temptable tmp LEFT JOIN #DatabaseTable db ON tmp.ID = db.ID WHERE db.ID is null
這會失敗,因為唯一標識符無效,因為它包含的“g”值不正確,超出了此數據類型的可接受範圍。發生這種情況是因為開發人員手動對其進行了更改以進行測試,因為他知道它不會存在於目標表中,但不知道有效的字元列表。
這是它拋出的錯誤;
(1 row(s) affected) Msg 8169, Level 16, State 2, Line 13 Conversion failed when converting from a character string to uniqueidentifier.
這是我所期望的行為。但是,在測試中搞亂時,我刪除了#DatabaseTable 上的主鍵,它執行得很好。現在我檢查了執行計劃,期望它將唯一標識符轉換為匹配
varchar(36)
,但是我看到了這個計算標量;CONVERT_IMPLICIT(uniqueidentifier,[tempdb].[dbo].[#temptable].[ID] as [tmp].[ID],0)
我似乎無法從 Microsoft 找到任何關於 CONVERT_IMPLICIT 實際語法的文件,所以我假設如果轉換失敗,最後的零是它所替換的,這是否是一個正確的假設(與
ISNULL
/相同COALESCE
)?另外,為什麼沒有 PK 也能正常工作,但沒有 PK 卻失敗了?
我能夠重現這一點。
這兩個計劃都有
#temptable
驅動嵌套循環連接的行。當
#DatabaseTable
有一個主鍵時,就有一個要查找的索引,因此連接的內部有一個查找。有必要將 varchar 轉換為 uniqueidentifier 以獲取要查找的值,此時轉換無效值的嘗試失敗。當沒有主鍵時,計劃會掃描嵌套循環的內部。它可以推遲評估,直到它有一行要比較,掃描時沒有行輸出
#DatabaseTable
(因為它是空的),所以CONVERT_IMPLICIT
永遠不需要評估。計算標量的位置可能會讓您不相信,但請參閱計算標量、表達式和執行計劃性能以了解更多資訊。