Arch manual pages

CREATE TABLE(7) SQL Commands CREATE TABLE(7)

CREATE TABLE - 定義一個新表

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name (
    { column_name data_type [ DEFAULT default_expr ] [ column_constraint [, ... ] ]
    | table_constraint
    | LIKE parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] }  [, ... ]
)
[ INHERITS ( parent_table [, ... ] ) ]
[ WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
where column_constraint is:
[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | UNIQUE | PRIMARY KEY |
  CHECK (expression) |
  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
    [ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
and table_constraint is:
[ CONSTRAINT constraint_name ]
{ UNIQUE ( column_name [, ... ] ) |
  PRIMARY KEY ( column_name [, ... ] ) |
  CHECK ( expression ) |
  FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
    [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

CREATE TABLE 將在當前數據庫創建一個新的, 初始爲空的表。該表將由發出此命令的用戶所有。

如果給出了模式名(比如,CREATE TABLE myschema.mytable ...), 那麼表是在指定模式中創建的。否則它在當前模式中創建。臨時表存在於一個特殊的模式裏, 因此創建臨時表的時候不能給出模式名。表名字必需和同一模式中其他表,序列,索引或者視圖相區別。

CREATE TABLE 還自動創建一個數據類型, 該數據類型代表對應該表一行的複合類型。 因此,表不能和同模式中的現有數據類型同名。

一個表的字段數不能超過 1600。(實際上,真正的限制比這低,因爲還有元組長度的約束)。

可選的約束子句聲明約束(或者測試),新行或者更新的行必須滿足這些約束才能成功插入或更新。 約束是一個它是一個 SQL 對象,它以多種方式協助我們協助我們在表上定義有效的數值集合。

定義約束又兩種方法:表約束和列約束。一個列約束是作爲一個列定義的一部分定義的。 而表約束並不和某個列綁在一起, 它可以作用於多於一個列上。每個列約束也可以寫成表約束; 如果某個約束隻影響一個列,那麼列約束只是符號上的簡潔方式而已。

TEMPORARY 或 TEMP
如果聲明瞭此參數,則該表創建爲臨時表。臨時表在會話結束時自動刪除, 或者是(可選)在當前事務的結尾(參閱下面的 ON COMMIT)。 現有同名永久表在臨時表存在期間在本會話過程中是不可見的, 除非它們是用模式修飾的名字引用的。 任何在臨時表上創建的索引也都會自動刪除。

我們可以選擇在 TEMPORARY 或 TEMP 前面放上 GLOBAL 或者 LOCAL。 這樣對 PostgreSQL 沒有任何區別,可以參閱 Compatibility [create_table(7)]。

table_name
要創建的表的名字(可以用模式修飾)。
column_name
在新表中要創建的字段名字。
data_type
該字段的數據類型。它可以包括數組說明符。
DEFAULT
DEFAULT 子句給它所出現的字段一個缺省數值。 該數值可以是任何不含變量的表達式(不允許使用子查詢和對本表中的其它字段的交叉引用)。 缺省表達式的數據類型必須和字段類型匹配。

缺省表達式將被用於任何未聲明該字段數值的插入操作。 如果字段上沒有缺省值,那麼缺省是 NULL。

LIKE 子句聲明一個表,新表自動從這個表裏面繼承所有字段名, 他們的數據類型,以及非空約束。

和 INHERITS 不同,新表與繼承過來的表之間在創建動作完畢之後是完全無關的。 插入新表的數據不會在父表中表現出來。

字段缺省表達式只有在聲明瞭 INCLUDING DEFAULTS 之後纔會繼承過來。 缺省是排除缺省表達式。

INHERITS ( parent_table [, ... ] )
可選的 INHERITS 子句聲明一列表,這個新表自動從這列表中繼承所有字段。 如果在多於一個父表中存在同名的字段,那麼就會報告一個錯誤,除非這些字段的數據類型在每個父表裏都是匹配的。 如果沒有衝突,那麼重複的字段在新表中融合成一個字段。 如果新表的字段名列表中包括和繼承的字段同名的,那麼它的數據類型也必須和上面一樣與繼承字段匹配,並且這些字段定義會融合成一個。 不過,同名的繼承和新字段聲明可以聲明不同的約束:所有的繼承過來的約束以及聲明的約束都融合到一起,並且全部應用於新表。 如果新表爲該字段明確的聲明瞭一個缺省數值,那麼此缺省數值覆蓋任何來自繼承字段聲明的缺省值。 否則,任何爲該字段聲明瞭缺省數值的父表都必須聲明相同的缺省,否則就會報告一個錯誤。
WITH OIDS
WITHOUT OIDS
這個可選的子句聲明新表中的行是否應該擁有賦予它們的 OID (對象標識)。 缺省是有 OID。(如果新表從任何有 OID 的表繼承而來,那麼就算這條命令說了 WITHOUT OIDS, 也會強制 WITH OIDS。)

聲明 WITHOUT OIDS 允許用戶禁止爲行或者表生成 OID。 這麼做對大表是值得的,因爲這樣可以減少 OID 消耗並且推遲 32 位 OID 計數器的消耗。 一旦該計數器重疊,那麼就不能再假設 OID 的唯一,這樣它的實用性就大打折扣。 聲明 WITHOUT OIDS 還會減少在磁盤上存儲每行的空間,每行減少 4 字節,因此也可以改進性能。

CONSTRAINT constraint_name
列或表約束的可選名字。如果沒有聲明,則由系統生成一個名字。
NOT NULL
字段不允許包含 NULL 數值。
NULL
該字段允許包含 NULL 數值。這是缺省。

這個子句的存在只是爲和那些非標準 SQL 數據庫兼容。 我們不建議在新應用中使用它。

UNIQUE (column constraint)
UNIQUE ( column_name [, ... ] ) (table constraint)
UNIQUE 聲明一個規則,表示一個表裏的一個或者多個獨立的字段組合的分組只能包含唯一的數值。 表的唯一約束的行爲和列約束的一樣,只不過多了跨多行的能力。

對於唯一約束的用途而言,系統認爲 NULL 數值是不相等的。

每個唯一表約束都必須命名一個字段的集合,該集合必須和其它唯一約束命名字段集合或者該表定義的主鍵約束不同。 (否則就只是同樣的約束寫了兩次。)

PRIMARY KEY (column constraint)
PRIMARY KEY ( column_name [, ... ] ) (table constraint)
主鍵約束表明表中的一個或者一些字段只能包含唯一(不重複)非 NULL 的數值。 從技術上講,PRIMARY KEY 只是 UNIQUE 和 NOT NULL 的組合,不過把一套字段標識爲主鍵同時也體現了模式設計的元數據, 因爲主鍵意味着其它表可以拿這套字段用做行的唯一標識。

一個表只能聲明一個主鍵,不管是作爲字段約束還是表約束。

主鍵約束應該定義在同個表上的一個與其它唯一約束所定義的不同的字段集合上。

CHECK (expression)
CHECK 約束聲明一個生成布爾結果的子句, 一次插入或者更新操作若想成功則裏面的新行或者被更新的行必須滿足這個條件。 聲明爲字段約束的檢查約束應該只引用該字段的數值,而在表約束裏出現的表達式可以引用多個字段。

目前,CHECK 表達式不能包含子查詢也不能引用除當前行字段之外的變量。

REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ] (column constraint)
FOREIGN KEY ( column [, ... ] )
這些子句聲明一個外鍵約束,外鍵約束聲明一個由新表中一列或者多列組成的組應該只包含匹配引用的表 reftable 中對應引用的字段 refcolumn 中的數值。 如果省略 refcolumn, 則使用 reftable 的主鍵。 被引用字段必須是被引用表中的唯一字段或者主鍵。

向這些字段插入的數值將使用給出的匹配類型與參考表中的參考列中的數值進行匹配。 有三種匹配類型:MATCH FULL, MATCH PARTIAL,和 MATCH SIMPLE,它也是缺省匹配類型。 MATCH FULL 將不允許一個多字段外鍵的字段爲 NULL,除非所有外鍵字段都爲 NULL。 MATCH SIMPLE 允許某些外鍵字段爲 NULL 而外鍵的其它部分不是 NULL。MATCH PARTIAL 還沒實現。

另外,當被參考字段中的數據改變的時候,那麼將對本表的字段中的數據執行某種操作。 ON DELETE 子句聲明當被參考表中的被參考行將被刪除的時候要執行的操作。 類似,ON UPDATE 子句聲明被參考表中被參考字段更新爲新值的時候要執行的動作。 如果該行被更新,但被參考的字段實際上沒有變化,那麼就不會有任何動作。 下面是每個子句的可能的動作:

NO ACTION
生成一個錯誤,表明刪除或者更新將產生一個違反外鍵約束的動作。 它是缺省動作。
RESTRICT
和 NO ACTION 一樣,只是動作不可推遲, 即使約束剩下的部分是可以推遲的也馬上發生。
CASCADE
刪除任何引用了被刪除行的行,或者分別把引用行的字段值更新爲被參考字段的新數值。
SET NULL
把引用行數值設置爲 NULL。
SET DEFAULT
把引用列的數值設置爲它們的缺省值。

如果主鍵字段經常更新,那麼我們給 REFERENCES 字段增加一個索引可能是合適的,這樣與 REFERENCES 字段相關聯的 NO ACTION 和 CASCADE 動作可以更有效地執行。

DEFERRABLE
NOT DEFERRABLE
這兩個關鍵字設置該約束是否可推遲。一個不可推遲的約束將在每條命令之後馬上檢查。 可以推遲的約束檢查可以推遲到事務結尾(使用 SET CONSTRAINTS [set_constraints(7)] 命令)。 缺省是 NOT DEFERRABLE。目前只有外鍵約束接受這個子句。所有其它約束類型都是不可推遲的。
INITIALLY IMMEDIATE
INITIALLY DEFERRED
如果約束是可推遲的,那麼這個子句聲明檢查約束的缺省時間。 如果約束是 INITIALLY IMMEDIATE, 那麼每條語句之後就檢查它。這個是缺省。如果約束是 INITIALLY DEFERRED,那麼只有在事務結尾才檢查它。 約束檢查的時間可以用 SET CONSTRAINTS [set_constraints(7)] 命令修改。
ON COMMIT
我們可以用 ON COMMIT 控制臨時表在事務塊結尾的行爲。這三個選項是:
PRESERVE ROWS
在事務結尾不發生任何特定的動作。這是缺省行爲。
DELETE ROWS
臨時表的所有行在每次事務結尾都被刪除。實際上,在每次提交的時候都自動 truncate(7)
DROP
在當前事務塊的結尾,臨時表將被刪除。

如果一個應用使用了 OID 標識表中的特定行,那麼我們建議在該表的 oid 字段上創建一個唯一約束,以確保該表的 OID 即使在計數器重疊之後也是唯一的。如果你需要一個整個數據庫範圍的唯一標識, 那麼就要避免假設 OID 是跨表唯一的,你可以用 tableoid 和行 OID 的組合來實現這個目的。 (將來的 PostgreSQL 很可能爲每個表使用獨立的 OID 計數器, 因此包括 tableoid 組成數據庫範圍內的唯一標識將是必須的,而不是可選的。)

提示: 對那些沒有主鍵的表,我們不建議使用 WITHOUT OIDS, 因爲如果既沒有 OID 又沒有唯一數據鍵字,那麼就很難標識特定的行。

PostgreSQL 自動爲每個唯一約束和主鍵約束創建一個索引以確保唯一性。 因此,我們不必爲主鍵字段創建明確的索引。(參閱 CREATE INDEX [create_index(7)]獲取更多信息。)
唯一約束和主鍵在目前的實現裏是不能繼承的。 這樣,如果把繼承和唯一約束組合在一起會導致無法運轉。

創建表 films 和 distributors:

CREATE TABLE films (
    code        char(5) CONSTRAINT firstkey PRIMARY KEY,
    title       varchar(40) NOT NULL,
    did         integer NOT NULL,
    date_prod   date,
    kind        varchar(10),
    len         interval hour to minute
);

CREATE TABLE distributors (
     did    integer PRIMARY KEY DEFAULT nextval('serial'),
     name   varchar(40) NOT NULL CHECK (name <> '')
);

創建一個帶有 2 維數組的表:

CREATE TABLE array (
    vector  int[][]
);

爲表 films 定義一個唯一表約束。 唯一表約束可以在表的一個或多個字段上定義:

CREATE TABLE films (
    code        char(5),
    title       varchar(40),
    did         integer,
    date_prod   date,
    kind        varchar(10),
    len         interval hour to minute,
    CONSTRAINT production UNIQUE(date_prod)
);

定義一個檢查列約束:

CREATE TABLE distributors (
    did     integer CHECK (did > 100),
    name    varchar(40)
);

定義一個檢查表約束:

CREATE TABLE distributors (
    did     integer,
    name    varchar(40)
    CONSTRAINT con1 CHECK (did > 100 AND name <> '')
);

爲表 films 定義一個主鍵表約束。 主鍵表約束可以定義在表上的一個或多個字段。

CREATE TABLE films (
    code        char(5),
    title       varchar(40),
    did         integer,
    date_prod   date,
    kind        varchar(10),
    len         interval hour to minute,
    CONSTRAINT code_title PRIMARY KEY(code,title)
);

爲表 distributors 定義一個主鍵約束。 下面兩個例子是等效的,第一個例子使用了表約束語法, 第二個使用了列約束表示法。

CREATE TABLE distributors (
    did     integer,
    name    varchar(40),
    PRIMARY KEY(did)
); 

CREATE TABLE distributors (
    did     integer PRIMARY KEY,
    name    varchar(40)
);

下面這個例子給字段 name 賦予了一個文本常量缺省值, 並且將字段 did 的缺省值安排爲通過選擇序列對象的下一個值生成。 modtime 的缺省值將是該行插入的時候的時間。

CREATE TABLE distributors (
    name      varchar(40) DEFAULT 'Luso Films',
    did       integer DEFAULT nextval('distributors_serial'),
    modtime   timestamp DEFAULT current_timestamp
);

在表 distributors 上定義兩個 NOT NULL 列約束,其中之一明確給出了名字:

CREATE TABLE distributors (
    did     integer CONSTRAINT no_null NOT NULL,
    name    varchar(40) NOT NULL
);

爲 name 字段定義一個唯一約束:

CREATE TABLE distributors (
    did     integer,
    name    varchar(40) UNIQUE
);

上面的和下面這樣作爲一個表約束聲明是一樣的:

CREATE TABLE distributors (
    did     integer,
    name    varchar(40),
    UNIQUE(name)
);

CREATE TABLE 遵循 SQL92 和 SQL99 的一個子集,一些例外情況在下面列出。

儘管 CREATE TEMPORARY TABLE 的語法和 SQL 標準的類似, 但是效果是不同的。在標準裏,臨時表只是定義一次並且自動存在(從空內容開始)於任何需要它們的會話中。 PostgreSQL 要求每個會話爲它們使用的每個臨時表發出它們自己的 CREATE TEMPORARY TABLE 命令。 這樣就允許不同的會話將相同的臨時表名字用於不同的目的,而標準的實現方法則把一個臨時表名字約束爲具有相同的表結構。

標準定義的臨時表的行爲被廣泛地忽略了。PostgreSQL 在這方面上地行爲類似於許多其它 SQL 數據庫

標準中在全局和局部地臨時表之間的區別在 PostgreSQL 裏不存在,因爲這種區別取決於模塊的概念,而 PostgreSQL 沒有這個概念。出於兼容考慮,PostgreSQL 將接受臨時表聲明中的 GLOBAL 和 LOCAL 關鍵字, 但是他們沒有作用。

臨時表的 ON COMMIT 子句也類似於 SQL 標準, 但是有些區別。如果忽略了 ON COMMIT 子句,SQL 聲明缺省的行爲是 ON COMMIT DELETE ROWS。 但是 PostgreSQL 裏的缺省行爲是 ON COMMIT PRESERVE ROWS。 在 SQL 裏不存在 ON COMMIT DROP。

SQL 標準說 CHECK 字段約束只能引用他們施用的字段; 只有 CHECK 表約束才能引用多個字段。PostgreSQL 並不強制這個限制;它把字段和表約束看作相同的東西。

NULL "約束"(實際上不是約束)是 PostgreSQL 對 SQL 標準的擴展, 包括它是爲了和其它一些數據庫系統兼容(以及爲了和 NOT NULL 約束對稱)。因爲它是任何字段的缺省,所以它的出現只是噪音而已。

通過 INHERITS 子句的多重繼承是 PostgreSQL 語言的擴展。 SQL99(但不包括 SQL92)使用不同的語法和語義定義了單繼承。 SQL99 風格的繼承還沒有在 PostgreSQL 中實現。

PostgreSQL 的 OID 的概念不標準。

PostgreSQL 允許創建沒有字段的表 (比如,CREATE TABLE foo();)。這是對 SQL 標準的擴展, 標準不允許存在零字段表。零字段表本身沒什麼用,但是禁止他們會給 ALTER TABLE DROP COLUMN帶來很奇怪的情況,所以,這個時候忽視標準的限制好想很清楚。

ALTER TABLE [alter_table(7)], DROP TABLE [drop_table(l)]

Postgresql 中文網站 何偉平 <laser@pgsqldb.org>

本頁面中文版由中文 man 手冊頁計劃提供。
中文 man 手冊頁計劃:https://github.com/man-pages-zh/manpages-zh
2003-11-02 SQL - Language Statements