2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3

CREATE DOMAIN

CREATE DOMAIN — 定義一個新域

概要

CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ domain_constraint [ ... ] ]

where domain_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | CHECK (expression) }

描述

CREATE DOMAIN 建立一個新域。域本質上是一種資料型別,帶有可選的約束(對允許的值集進行限制)。定義域的使用者成為其所有者。

如果給出了模式名(例如,CREATE DOMAIN myschema.mydomain ...),則該域將在指定的模式中建立。否則,它將在當前模式中建立。域的名稱在其模式中存在的型別和域之間必須是唯一的。

域可用於將欄位的常見約束抽象到一個位置進行維護。例如,多個表可能包含電子郵件地址列,所有這些列都需要相同的 CHECK 約束來驗證地址語法。應定義一個域,而不是單獨設定每個表的約束。

要能夠建立域,您必須擁有底層型別上的 USAGE 許可權。

引數

name

要建立的域的名稱(可選模式限定)。

data_type

域的底層資料型別。這可以包括陣列說明符。

collation

域的可選排序規則。如果未指定排序規則,則域具有與其底層資料型別相同的排序規則行為。如果指定了 COLLATE,則底層型別必須是可排序的。

DEFAULT expression

DEFAULT 子句為域資料型別列指定預設值。值是任何不含變數的表示式(但不能使用子查詢)。預設表示式的資料型別必須與域的資料型別匹配。如果未指定預設值,則預設值為 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 的擴充套件(另請參見 相容性)。

另請參閱

ALTER DOMAIN, DROP DOMAIN

提交更正

如果您在文件中發現任何不正確、與您的特定功能體驗不符或需要進一步澄清的內容,請使用 此表單報告文件問題。