首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 實現「非 NULL 值唯一」約束:CHECK 約束與 INSTEAD OF TRIGGER 兩大方案

     編輯:MySQL 資料庫相關知識

需求:某欄位允許 NULL,但**非 NULL 值必須唯一**。標準 UNIQUE 約束僅允許單一 NULL,不符合需求。本文提供兩種程式化實現方案。

方案一:觸發器 (適用所有版本)

CREATE TABLE t1 (c1 INT NULL, c2 CHAR(5) NULL)
GO
CREATE TRIGGER mytrigger ON t1 FOR INSERT, UPDATE
AS
BEGIN
    IF (SELECT MAX(cnt) FROM (
        SELECT COUNT(i.c1) AS cnt
        FROM t1 JOIN inserted i ON t1.c1 = i.c1
        GROUP BY i.c1
    ) x) > 1
        ROLLBACK TRAN
END
  • 檢查插入/更新後非 NULL 值是否重複。
  • 缺點:觸發器開銷、平行執行計畫可能受影響。

方案二:INSTEAD OF TRIGGER (SQL 2000+ 推薦)

  • 攔截 INSERT/UPDATE,自訂邏輯判斷後再決定是否執行實際 DML。
  • 可精確控制錯誤訊息、避免 Rollback 開銷。
  • 參考文獻:
    - Tricks with INSTEAD OF Triggers (InstantDoc 15828)
    - INSTEAD OF Triggers on VIEWs (InstantDoc 15791)
    - INSTEAD OF Triggers (InstantDoc 15524)

現代替代方案:篩選索引 (SQL Server 2008+)

CREATE UNIQUE INDEX UX_t1_c1_NotNull ON t1(c1) WHERE c1 IS NOT NULL
  • **原生支援、效能最佳、無觸發器開銷**。
  • 強烈建議 SQL Server 2008 及以上版本直接使用此語法。

總結

方案適用版本效能維護性推薦度
AFTER TRIGGER所有中中舊版本備選
INSTEAD OF TRIGGER2000+中高2000/2005 首選
篩選索引2008+高高現代首選

升級至 SQL Server 2008+ 後,請直接使用 CREATE UNIQUE INDEX ... WHERE column IS NOT NULL,最簡潔高效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved