首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 空值處理策略:COUNT、空值運算與外鍵三大議題

     編輯:關於SqlServer

空值是資料庫開發繞不開的議題。本文聚焦三大實務場景:彙總函數計數差異、空值參與運算的陷阱、外鍵條件約束與空值的互動,提供具體解決方案與程式碼驗證。

議題一:COUNT(*) vs COUNT(欄位) vs COUNT(ISNULL(欄位,值))

行為差異

函數統計對象空值處理
COUNT(*)所有資料列包含空值列
COUNT(欄位)該欄位非空值忽略空值
COUNT(ISNULL(欄位,替代值))所有資料列空值被替代值取代 → 計入統計

驗證腳本

SET NOCOUNT ON
GO
CREATE TABLE xCount (
    pkey1 INT IDENTITY NOT NULL CONSTRAINT pk_xCount PRIMARY KEY,
    Col1 INT NULL
)
GO
INSERT xCount (Col1) VALUES (10), (15), (20), (NULL)
GO

SELECT 
    AVG(Col1) AS AvgWithoutIsNull,
    AVG(ISNULL(Col1,0)) AS AvgWithIsNull,
    COUNT(Col1) AS CountCol1,
    COUNT(ISNULL(Col1,0)) AS CountIsNullCol1,
    COUNT(*) AS CountStar
FROM xCount
GO
-- 結果:
-- AvgWithoutIsNull = 15  (10+15+20)/3
-- AvgWithIsNull    = 11  (10+15+20+0)/4
-- CountCol1        = 3   (忽略 NULL)
-- CountIsNullCol1  = 4   (NULL→0 計入)
-- CountStar        = 4   (所有列)

DROP TABLE xCount
GO

實務建議

  • 需統計**所有列** → COUNT(*)
  • 需統計**該欄位有值的列** → COUNT(欄位)
  • 需統計**所有列但空值視為特定值** → COUNT(ISNULL(欄位,值))
  • 彙總函數 (AVG, SUM, MIN, MAX) 皆**自動忽略空值**,若需空值參與運算必須 ISNULL/COALESCE

議題二:空值參與運算與比較的陷阱

三值邏輯真理表

運算結果說明
NULL + 100NULL算術運算任一操作數為 NULL → 結果 NULL
NULL = NULLUNKNOWN (非 TRUE)比較運算任一操作數為 NULL → UNKNOWN,WHERE/IF 視為 FALSE
NULL <> 'abc'UNKNOWN同理
NULL IS NULLTRUE專用判斷語法
COALESCE(NULL, 'a', 'b')'a'回傳第一個非 NULL 值

常見錯誤與修正

-- 錯誤:想找出沒有電話的客戶
SELECT * FROM Customers WHERE Phone <> ''  -- 遺漏 Phone IS NULL 的列!

-- 正確:
SELECT * FROM Customers WHERE Phone IS NULL OR Phone = ''
-- 或
SELECT * FROM Customers WHERE ISNULL(Phone, '') = ''

議題三:外鍵條件約束與空值

規則

  • 外鍵欄位**允許 NULL** (除非額外加 NOT NULL)
  • 外鍵值為 NULL 時,**不檢查** 參考資料表是否存在對應值
  • 這符合業務邏輯:「尚未指派/不適用」不應強制關聯

驗證範例

CREATE TABLE Departments (
    DeptID INT PRIMARY KEY,
    DeptName VARCHAR(50)
)

CREATE TABLE Employees (
    EmpID INT PRIMARY KEY,
    EmpName VARCHAR(50),
    DeptID INT NULL,  -- 允許 NULL
    CONSTRAINT FK_Emp_Dept FOREIGN KEY (DeptID) REFERENCES Departments(DeptID)
)

INSERT INTO Departments VALUES (1, 'IT'), (2, 'HR')
INSERT INTO Employees VALUES (101, 'Alice', 1), (102, 'Bob', NULL)  -- Bob 無部門 → 允許
-- INSERT INTO Employees VALUES (103, 'Carol', 99)  -- 違反 FK:DeptID=99 不存在 → 錯誤

業務場景:強制關聯 vs 可選關聯

業務需求外鍵定義範例
每筆訂單必須有客戶CustID INT NOT NULL REFERENCES Customers訂單-客戶 (強制)
員工可能暫無部門DeptID INT NULL REFERENCES Departments員工-部門 (可選)
產品可能暫無分類CategoryID INT NULL REFERENCES Categories產品-分類 (可選)

綜合最佳實務

  1. DDL 階段:依業務語意決定 NULL/NOT NULL,外鍵同步設定
  2. 查詢階段:COUNT(*) 統計列數,COUNT(欄位) 統計非空值,混用 ISNULL/COALESCE 控制運算行為
  3. 應用層:DTO/實體類別對應欄位用 Nullable(Of T) (VB) / T? (C#) 明確表達可空性
  4. 報表層:統一空值顯示文字 (如「N/A」、「未提供」、「--」),避免空白欄位造成誤讀
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved