CREATE DOMAIN — 定義一個新的資料域
CREATE DOMAINname
[ AS ]data_type
[ COLLATEcollation
] [ DEFAULTexpression
] [domain_constraint
[ ... ] ] wheredomain_constraint
is: [ CONSTRAINTconstraint_name
] { NOT NULL | NULL | CHECK (expression
) }
CREATE DOMAIN
建立一個新的資料域。資料域本質上是一種具有可選約束(對允許的值集進行限制)的資料類型。定義資料域的使用者將成為它的擁有者。
如果給出了一個模式名稱(例如,CREATE DOMAIN myschema.mydomain ...
),則該資料域會在指定的模式中被建立。否則,它會在目前的模式中被建立。資料域名在該模式中已存在的類型和資料域中必須是唯一的。
資料域可用於將欄位上的常見約束抽象到一個用於維護的單一位置。例如,多個資料表可能包含電子郵件地址欄位,所有欄位都需要相同的 CHECK 約束來驗證地址語法。定義一個資料域,而不是單獨設定每個資料表的約束。
要能夠建立資料域,你必須在底層類型上具有 USAGE
權限。
name
要建立的資料域名稱(可選擇使用模式限定)。
data_type
資料域的底層資料類型。這可以包含陣列指定詞。
collation
資料域的可選排序規則。如果未指定排序規則,則該資料域的排序規則行為與其底層資料類型相同。如果指定了 COLLATE
,則底層類型必須是可排序的。
DEFAULT expression
DEFAULT
子句指定了資料域資料類型欄位的預設值。該值可以是任何無變數的運算式(但不允許子查詢)。預設運算式的資料類型必須與資料域的資料類型相符。如果未指定預設值,則預設值為空值。
預設運算式將用於任何未指定欄位值的插入作業中。如果為特定欄位定義了預設值,它會覆蓋與資料域關聯的任何預設值。反過來,資料域預設值會覆蓋與底層資料類型關聯的任何預設值。
CONSTRAINT constraint_name
約束的可選名稱。如果未指定,系統會產生一個名稱。
NOT NULL
此資料域的值會被阻止為空值(但請參閱下面的說明)。
NULL
允許此資料域的值為空值。這是預設值。
這個子句僅用於與非標準的 SQL 資料庫相容。不鼓勵在新應用程式中使用它。
CHECK (expression
)
CHECK
子句指定完整性約束或測試,資料域的值必須滿足這些約束或測試。每個約束必須是一個產生布林結果的運算式。它應該使用關鍵字 VALUE
來引用被測試的值。求值為 TRUE 或 UNKNOWN 的運算式會成功。如果運算式產生 FALSE 結果,則會報告一個錯誤,並且不允許將該值轉換為資料域類型。
目前,CHECK
運算式不能包含子查詢,也不能引用 VALUE
以外的變數。
當資料域有多個 CHECK
約束時,它們將按名稱的字母順序進行測試。(9.5 之前的 PostgreSQL 版本不遵守 CHECK
約束的任何特定觸發順序。)
資料域約束,尤其是 NOT NULL
,在將值轉換為資料域類型時會被檢查。儘管存在這樣的約束,但名義上屬於資料域類型的欄位有可能讀取為空值。例如,如果在外部聯結查詢中,資料域欄位位於外部聯結的可空側,則會發生這種情況。一個更微妙的例子是
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
空的純量子 SELECT 將產生一個被認為是資料域類型的空值,因此不會對其應用進一步的約束檢查,並且插入將成功。
由於 SQL 的一般假設,即空值是每個資料類型的有效值,因此很難避免此類問題。因此,最佳實務是設計資料域的約束,以便允許空值,然後根據需要在資料域類型的欄位上應用欄位 NOT NULL
約束,而不是直接應用於資料域類型。
PostgreSQL 假設 CHECK
約束的條件是不變的,也就是說,對於相同的輸入值,它們總是會給出相同的結果。 這個假設是驗證 CHECK
約束的理由,僅在一個值首次轉換為網域類型時檢查,而不是在其他時間檢查。(這基本上與表格 CHECK
約束的處理方式相同,如第 5.5.1 節中所述。)
打破此假設的一個常見範例是在 CHECK
表達式中引用使用者自定義函數,然後更改該函數的行為。PostgreSQL 並不禁止這樣做,但如果存在違反 CHECK
約束的網域類型的儲存值,它將不會注意到。 這將導致後續的資料庫傾印和恢復失敗。 處理這種更改的建議方法是刪除約束(使用 ALTER DOMAIN
),調整函數定義,然後重新添加約束,從而針對儲存的資料重新檢查它。
確保網域 CHECK
表達式不會引發錯誤也是一個好的做法。
此範例建立 us_postal_code
資料類型,然後在表格定義中使用該類型。 使用正則表達式測試來驗證該值是否看起來像有效的美國郵遞區號
CREATE DOMAIN us_postal_code AS TEXT CHECK( VALUE ~ '^\d{5}$' OR VALUE ~ '^\d{5}-\d{4}$' ); CREATE TABLE us_snail_addy ( address_id SERIAL PRIMARY KEY, street1 TEXT NOT NULL, street2 TEXT, street3 TEXT, city TEXT NOT NULL, postal us_postal_code NOT NULL );
命令 CREATE DOMAIN
符合 SQL 標準。
此命令中的語法 NOT NULL
是 PostgreSQL 的擴充功能。(符合標準的寫法是 CHECK (VALUE IS NOT NULL)
。但是,根據標題為「Notes」的部分,最好還是避免在實踐中使用此類約束。)NULL
「約束」是 PostgreSQL 擴充功能(另請參閱相容性)。
如果您在文件中發現任何不正確、與特定功能的體驗不符或需要進一步澄清的地方,請使用此表單來回報文件問題。