SYNOPSIS
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 ]
DESCRIPTION 描述
CREATE TABLE 將在當前數據庫創建一個新的, 初始為空的表。該表將由發出此命令的用戶所有。
如果給出了模式名(比如,CREATE TABLE myschema.mytable ...), 那么表是在指定模式中創建的。否則它在當前模式中創建。臨時表存在於一個特殊的模式里, 因此創建臨時表的時候不能給出模式名。表名字必需和同一模式中其他表,序列,索引或者視圖相區別。
CREATE TABLE 還自動創建一個數據類型, 該數據類型代表對應該表一行的復合類型。 因此,表不能和同模式中的現有數據類型同名。
一個表的字段數不能超過 1600。(實際上,真正的限制比這低,因為還有元組長度的約束)。
可選的約束子句聲明約束(或者測試),新行或者更新的行必須滿足這些約束才能成功插入或更新。 約束是一個它是一個 SQL 對象,它以多種方式協助我們協助我們在表上定義有效的數值集合。
定義約束又兩種方法:表約束和列約束。一個列約束是作為一個列定義的一部分定義的。 而表約束並不和某個列綁在一起, 它可以作用於多於一個列上。每個列約束也可以寫成表約束; 如果某個約束只影響一個列,那么列約束只是符號上的簡潔方式而已。
PARAMETERS 參數
- 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
-
在當前事務塊的結尾,臨時表將被刪除。
NOTES 注意
- *
-
如果一個應用使用了 OID 標識表中的特定行,那么我們建議在該表的 oid 字段上創建一個唯一約束,以確保該表的 OID 即使在計數器重疊之后也是唯一的。如果你需要一個整個數據庫范圍的唯一標識, 那么就要避免假設 OID 是跨表唯一的,你可以用 tableoid 和行 OID 的組合來實現這個目的。 (將來的 PostgreSQL 很可能為每個表使用獨立的 OID 計數器, 因此包括 tableoid 組成數據庫范圍內的唯一標識將是必須的,而不是可選的。)- 提示: 對那些沒有主鍵的表,我們不建議使用 WITHOUT OIDS, 因為如果既沒有 OID 又沒有唯一數據鍵字,那么就很難標識特定的行。
- *
- PostgreSQL 自動為每個唯一約束和主鍵約束創建一個索引以確保唯一性。 因此,我們不必為主鍵字段創建明確的索引。(參閱 CREATE INDEX [ create_index(7)]獲取更多信息。)
- *
-
唯一約束和主鍵在目前的實現里是不能繼承的。 這樣,如果把繼承和唯一約束組合在一起會導致無法運轉。
EXAMPLES 例子
創建表 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) );
COMPATIBILITY 兼容性
CREATE TABLE 遵循 SQL92 和 SQL99 的一個子集,一些例外情況在下面列出。
TEMPORARY TABLES 臨時表
盡管 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。
COLUMN CHECK CONSTRAINTS 字段檢查約束
SQL 標准說 CHECK 字段約束只能引用他們施用的字段; 只有 CHECK 表約束才能引用多個字段。PostgreSQL 並不強制這個限制;它把字段和表約束看作相同的東西。
NULL ``CONSTRAINT'' NULL約束
NULL "約束"(實際上不是約束)是 PostgreSQL 對 SQL 標准的擴展, 包括它是為了和其它一些數據庫系統兼容(以及為了和 NOT NULL 約束對稱)。因為它是任何字段的缺省,所以它的出現只是噪音而已。
INHERITANCE 繼承
通過 INHERITS 子句的多重繼承是 PostgreSQL 語言的擴展。 SQL99(但不包括 SQL92)使用不同的語法和語義定義了單繼承。 SQL99 風格的繼承還沒有在 PostgreSQL 中實現。
OBJECT IDS 對象ID
PostgreSQL 的 OID 的概念不標准。
ZERO-COLUMN TABLES 零行表
PostgreSQL 允許創建沒有字段的表 (比如,CREATE TABLE foo();)。這是對 SQL 標准的擴展, 標准不允許存在零字段表。零字段表本身沒什么用,但是禁止他們會給 ALTER TABLE DROP COLUMN帶來很奇怪的情況,所以,這個時候忽視標准的限制好想很清楚。