CHECK 條件約束

CHECK 條件約束限制資料行接受的值,藉此強制值域完整性。 它們類似於 FOREIGN KEY 條件約束,用來控制放入資料行的值。 其間的差異在於它們如何判定哪些值有效:FOREIGN KEY 條件約束從另一個資料表取得有效值清單,而 CHECK 條件約束則會從不是以另一資料行中之資料為基礎的邏輯運算式來判定有效值。例如,可以藉由建立只允許範圍從 $15,000 到 $100,000 之資料的 CHECK 條件約束,來限制 salary 資料行的值範圍。這可防止輸入的薪水超過一般的薪水範圍。

您可使用能根據邏輯運算子傳回 TRUE 或 FALSE 的任何邏輯 (布林) 運算式來建立 CHECK 條件約束。 前述範例中的邏輯運算式可表示為: salary >= 15000 AND salary <= 100000。

您可以將多個 CHECK 條件約束套用到單一資料行。 您也可以在資料表層級建立單一 CHECK 條件約束,將它套用到多個資料行。 例如,多重資料行的 CHECK 條件約束可用來確認 country/region 資料行值為 USA 的任何資料列,其 state 資料行內也會擁有兩個字元的值。 這允許可在某一個位置上檢查多個條件。

警告注意事項注意

包括明確或隱含資料類型轉換的條件約束可能會導致某些作業失敗。 例如,在資料分割切換來源的資料表上所定義的此類條件約束,可能會導致 ALTER TABLE...SWITCH 作業失敗。 應避免在條件約束定義中進行資料類型轉換。

CHECK 條件約束的限制

CHECK 條件約束會拒絕評估為 FALSE 的值。 因為 Null 值會評估為 UNKNOWN,所以若其出現於運算式中,可能會覆寫條件約束。 例如,假設您將條件約束放在 int 資料行 MyColumn 中,指定 MyColumn 只能包含 10 這個值 (MyColumn=10)。 如果您將 NULL 值插入 MyColumn,則 Database Engine 會插入 NULL 且不會傳回錯誤。

CHECK 條件約束會針對資料表中的所有資料列進行檢查,當檢查的條件不為 FALSE 時,會傳回 TRUE。 如果剛建立的資料表沒有任何資料列,則這個資料表上的任何 CHECK 條件約束都將視為有效。 這種情況可能會產生非預期結果,如下列範例所示。

CREATE TABLE CheckTbl (col1 int, col2 int);
GO
CREATE FUNCTION CheckFnctn()
RETURNS int
AS 
BEGIN
   DECLARE @retval int
   SELECT @retval = COUNT(*) FROM CheckTbl
   RETURN @retval
END;
GO
ALTER TABLE CheckTbl
ADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1 );
GO

要加入的 CHECK 條件約束會指定 CheckTbl 資料表中至少要有一個資料列。 不過,因為資料表中沒有任何資料列,能據以檢查這個條件約束的條件,所以 ALTER TABLE 陳述式會成功執行。

CHECK 條件約束不會在 DELETE 陳述式執行期間進行驗證。 因此,若在具有某些類型之 CHECK 條件約束的資料表上執行 DELETE 陳述式,可能會產生非預期的結果。 例如,考慮在 CheckTbl 資料表上執行的下列陳述式。

INSERT INTO CheckTbl VALUES (10, 10)
GO
DELETE CheckTbl WHERE col1 = 10;

即使 CHECK 條件約束會指定資料表 CheckTbl 至少必須具有 1 個資料列,DELETE 陳述式也會執行成功。