Sql-Server

不正確的唯一標識符在沒有主鍵的情況下工作,但在主鍵下失敗

  • May 5, 2017

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永遠不需要評估。

計算標量的位置可能會讓您不相信,但請參閱計算標量、表達式和執行計劃性能以了解更多資訊。

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