CREATE DOMAIN — 定義一個新域
CREATE DOMAINname[ AS ]data_type[ COLLATEcollation] [ DEFAULTexpression] [domain_constraint[ ... ] ] wheredomain_constraintis: [ CONSTRAINTconstraint_name] { NOT NULL | NULL | CHECK (expression) }
CREATE DOMAIN 建立一個新域。域本質上是一種資料型別,帶有可選的約束(對允許的值集進行限制)。定義域的使用者成為其所有者。
如果給出了模式名(例如,CREATE DOMAIN myschema.mydomain ...),則該域將在指定的模式中建立。否則,它將在當前模式中建立。域的名稱在其模式中存在的型別和域之間必須是唯一的。
域可用於將欄位的常見約束抽象到一個位置進行維護。例如,多個表可能包含電子郵件地址列,所有這些列都需要相同的 CHECK 約束來驗證地址語法。應定義一個域,而不是單獨設定每個表的約束。
要能夠建立域,您必須擁有底層型別上的 USAGE 許可權。
name要建立的域的名稱(可選模式限定)。
data_type域的底層資料型別。這可以包括陣列說明符。
collation域的可選排序規則。如果未指定排序規則,則域具有與其底層資料型別相同的排序規則行為。如果指定了 COLLATE,則底層型別必須是可排序的。
DEFAULT expressionDEFAULT 子句為域資料型別列指定預設值。值是任何不含變數的表示式(但不能使用子查詢)。預設表示式的資料型別必須與域的資料型別匹配。如果未指定預設值,則預設值為 null 值。
預設表示式將用於不為列指定值的任何插入操作。如果為特定列定義了預設值,它將覆蓋與域關聯的任何預設值。反過來,域預設值將覆蓋與底層資料型別關聯的任何預設值。
CONSTRAINT constraint_name約束的可選名稱。如果未指定,系統將生成一個名稱。
NOT NULL不允許此域的值為 null(但請參見下面的註釋)。
NULL此域的值允許為 null。這是預設設定。
此子句僅用於與非標準 SQL 資料庫相容。在新應用程式中不推薦使用它。
CHECK (expression)CHECK 子句指定域的值必須滿足的完整性約束或測試。每個約束都必須是一個產生布爾結果的表示式。它應該使用關鍵字 VALUE 來引用正在測試的值。求值為 TRUE 或 UNKNOWN 的表示式將成功。如果表示式產生 FALSE 結果,則會報告錯誤,並且不允許將該值轉換為域型別。
當前,CHECK 表示式不能包含子查詢,也不能引用除了 VALUE 之外的變數。
當域具有多個 CHECK 約束時,它們將按名稱的字母順序進行測試。(PostgreSQL 9.5 之前的版本不遵循任何特定的 CHECK 約束執行順序。)
域約束,特別是 NOT NULL,在將值轉換為域型別時進行檢查。即使存在此類約束,名為域型別的列也可能被讀取為 null。例如,這可能發生在外部連線查詢中,如果域列位於外部連線的可空端。一個更微妙的例子是
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
空的標量子查詢將產生一個 null 值,該值被視為域型別,因此不會對其應用進一步的約束檢查,並且插入將成功。
由於 SQL 的總體假設是 null 值是每種資料型別的有效值,因此很難避免此類問題。因此,最佳實踐是設計域約束,使其允許 null 值,然後根據需要將列 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 的擴充套件(另請參見 相容性)。
如果您在文件中發現任何不正確、與您的特定功能體驗不符或需要進一步澄清的內容,請使用 此表單報告文件問題。