KB981037 - 修正:在 SQL Server 2008 中,當您執行使用 ISNULL () 函數選取可為 Null 資料行值的查詢時,出現「嘗試將非 Null 資料行的值設為 NULL」錯誤訊息

Microsoft 會發佈 Microsoft SQL Server 2008 修正程式作為一個可下載的檔案。 由於修正程式是累積式,因此每個新版本都包含所有 Hotfix 和先前 SQL Server 2008 修正程式版本中包含的所有安全性修正程式。

症狀

請考慮以下案例:

  • 在 Microsoft SQL Server 2008 中,您執行的查詢會使用 ISNull () 函數來選取可為 Null 資料行中的值。
  • 包含可為 Null 資料行的資料表與可為 Null 資料行的另一個資料表結合。
  • 查詢最佳化工具所建立的查詢計劃會使用雜湊聯結、多工緩衝處理或 JOIN 運算子下方的排序表格。

在此案例中,您收到下列錯誤訊息:

注意

Msg 681, Level 16, State 3, Line 2

嘗試將非 NULL 資料行的值設為 NULL。

原因

查詢最佳化工具會判斷 ISNULL () 函數中參照的欄為不可 null 值,因為連接運算子拒絕 NULL 值。 然後,在查詢計劃中,查詢最佳化工具會將 ISNull () 函數中的運算式推送到 JOIN 運算子下方。 此外,運算式的值可以是 NULL。 不過,查詢最佳化工具不會重新衍生運算式的可為 null 屬性。 然後,在查詢計劃中,使用工作表來實作雜湊聯結、假脫線或包含運算式的排序表。 此外,工作資料表中的對應資料行會宣告為不可為 Null。 當 SQL Server 查詢引擎嘗試將 NULL 值插入工作表時,會發生錯誤。

解決方式

此問題的修正程式最初在 SQL Server 2008 Service Pack 1 的累積更新 7 中發行。 如需有關此累積更新套件的詳細資訊,請按一下下面的文章編號,檢視「Microsoft 知識庫」中的文章:

979065 SQL Server 2008 Service Pack 1 累積更新套件 7 注意:由於這些組建是累積的,因此每個新發行的修正程式都包含所有 Hotfix 和所有安全性修正程式,這些都包含在上一個 SQL Server 2008 修正程式版本中。 建議您考慮套用包含此 Hotfix 的最新修正版本。 如需詳細資訊,請按一下下面的文章編號,檢視「Microsoft 知識庫」中的文章:

970365 發行 SQL Server 2008 Service Pack 1 之後所發行的 SQL Server 2008 組建
Microsoft SQL Server 2008 Hotfix 是為特定 SQL Server Service Pack 而建立。 您必須將 SQL Server 2008 Service Pack 1 Hotfix 套用至 SQL Server 2008 Service Pack 1 的安裝。 預設情況下,SQL Server Service Pack 中提供的任何 Hotfix 都會包含在下一個 SQL Server Service Pack 中。

因應措施

請使用下列方法之一解決此問題:

方法 1

從查詢中移除 ISNull () 函數。

注意:因為這個函數中的欄來自拒絕 NULL 值的 JOIN 運算子,所以 ISNULL () 函數是重複的。

方法 2

重寫查詢,讓查詢計劃不使用雜湊聯結、多工緩衝處理或排序表格。 例如,如果您的查詢包含 ORDER BY 子句,請建立提供必要排序並包含所有必要欄的叢集或涵蓋索引。 當您使用這個方法時,查詢最佳化工具不會使用排序表格。

狀態

Microsoft 已確認這是「適用對象」一節中列出的 Microsoft 產品中的問題。

參考資料

如需有關 SQL Server 累加式服務模型的資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:

935897 來自 SQL Server 團隊之可傳遞解決回報問題的 Hotfix 的累加服務模型 (機器翻譯)

如需有關 SQL Server 更新命名架構的詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:

822499 Microsoft SQL Server 軟體更新套件的新命名架構

如需有關軟體更新術語的詳細資訊,請按一下下面的文章編號,檢視「Microsoft 知識庫」中的文章:

824684 描述Microsoft軟體更新所使用的標準術語說明