2014-03-02 85 views
1

我對CHECK的語法存在問題,特別是它意味着與列一起出現的方式。一個例子來說明這具體:抱怨`CHECK`的語法

CREATE OR REPLACE FUNCTION greater_than_10(x INTEGER) RETURNS BOOLEAN AS 
'SELECT $1>10;' 
LANGUAGE SQL; 

CREATE TABLE A (
    v1 INTEGER CHECK (greater_than_10(v1)), 
    v2 INTEGER CHECK (greater_than_10(v2)) 
) 

這裏是我的問題:爲什麼CHECK必須一起出現的列?如果它只是出現在列的旁邊,那麼傳遞參數是多餘的,因爲該列的值應該是隱含的。然而,下面的語法是同樣正確:

CREATE TABLE A (
    v1 INTEGER CHECK (greater_than_10(v2)), 
    v2 INTEGER CHECK (greater_than_10(v1)) 
) 

其證明CHECK未綁定到特定的列,而是整個行,並且可以使用從其他的行,以及在下面的示例值:

CREATE OR REPLACE FUNCTION sum_more_than_10(x INTEGER, y INTEGER) RETURNS BOOLEAN AS 
'SELECT $1+$2>10;' 
LANGUAGE SQL;   

CREATE TABLE A (
    v1 INTEGER CHECK (sum_more_than_10(v1, v2)), 
    v2 INTEGER 
) 

CHECK是否出現在v1列或列v2最後這種情況沒有什麼區別。那麼爲什麼CHECK在語法上與列綁定?我錯過了什麼?

回答

3

CHECK約束中的表達式不必是單參數函數調用。您可以編寫CHECK (v1 > 10)而不是調用您的greater_than_10函數。或者你可以寫CHECK (20 < (v1 * 2))。列名可以出現在表達式的任何位置;這並不意味着在任何特定的地方。

此外,列約束實際上只是表約束的語法糖。當你寫

v1 INTEGER CHECK (v1 > 10), 
v2 INTEGER CHECK (v2 > 10) 

它等同於寫

v1 INTEGER, 
v2 INTEGER, 
CHECK (v1 > 10), 
CHECK (v2 > 10) 

你甚至可以結合兩種成一個約束:

v1 INTEGER, 
v2 INTEGER, 
CHECK ((v1 > 10) AND (v2 > 10)) 
+0

這正是我要說的,我給的例子。那麼它不是一種糟糕的語法選擇,它允許CHECK出現在列的旁邊,實際上它適用於整行?而且,當CHECK確實出現在列的旁邊時(這暗示開發人員暗示CHECK只使用該列的值?) –

+1

@MarcusJuniusBrutus:這就是SQL標準定義語法的方式。 –

+0

@MarcusJuniusBrutus,列名不能是隱式的,因爲您必須編寫有效的布爾表達式。你會如何寫'CHECK(name = lower(name))'而不提'name'? – Wyzard