| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Fast Forward | Next | |
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 } ]
[ TABLESPACE tablespace ]
這裡 column_constraint 可以是:
[ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
UNIQUE [ USING INDEX TABLESPACE tablespace ] |
PRIMARY KEY [ USING INDEX TABLESPACE tablespace ] |
CHECK (expression) |
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
[ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
而 table_constraint 可以是:
[ CONSTRAINT constraint_name ]
{ UNIQUE ( column_name [, ... ] ) [ USING INDEX TABLESPACE tablespace ] |
PRIMARY KEY ( column_name [, ... ] ) [ USING INDEX TABLESPACE tablespace ] |
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 還自動建立一個資料類型, 該資料類型代資料表對應該資料表一行的復合類型。 因此,資料表不能和同模式中的現有資料類型同名。
可選的約束子句聲明約束(測試),新行或者更新的行必須滿足這些約束才能成功插入或更新。 約束是一個它是一個 SQL 對象,它以多種方式協助我們協助我們在資料表上定義有效的數值集合。
定義約束又兩種方法:資料表約束和列約束。一個列約束是作為一個列定義的一部分定義的。 而資料表約束並不和某個列綁在一起, 它可以作用於多於一個列上。每個列約束也可以寫成資料表約束; 如果某個約束只影響一個列,那麼列約束只是符號上的簡潔方式而已。
如果聲明了此參數,則該資料表建立為臨時資料表。臨時資料表在會話結束時自動刪除, 或者是(可選)在目前交易的結尾(參閱下面的 ON COMMIT)。 現有同名永久資料表在臨時資料表存在期間在本會話過程中是不可見的, 除非它們是用模式修飾的名字引用的。 任何在臨時資料表上建立的索引也都會自動刪除。
我們可以選擇在 TEMPORARY 或 TEMP 前面放上 GLOBAL 或者 LOCAL。 這樣對 PostgreSQL 沒有任何區別,可以參閱 相容性.
要建立的資料表的名字(可以用模式修飾)。
在新資料表中要建立的字串名字。
該字串的資料類型。它可以包括數組說明符。有關 PostgreSQL 支援的資料類型的更多訊息, 請參考 Chapter 8。
DEFAULT 子句給它所出現的字串一個預設數值。 該數值可以是任何不含變量的資料表達式(不允許使用子查詢和對本資料表中的其它字串的交叉引用)。 預設資料表達式的資料類型必須和字串類型匹配。
預設資料表達式將被用於任何未聲明該字串數值的插入操作。 如果字串上沒有預設值,那麼預設是 NULL。
可選的 INHERITS 子句聲明一列資料表,這個新資料表自動從這列資料表中繼承所有字串。
使用 INHERITS 在新的子資料表和其父資料表之間建立一個永久的關係。 對父資料表結構的修改通常也會傳播到子資料表,預設時,掃瞄父資料表的時候也會掃瞄子資料表。
如果在多於一個父資料表中存在同名的字串,那麼就會報告一個錯誤,除非這些字串的資料類型在每個父資料表裡都是匹配的。 如果沒有衝突,那麼重複的字串在新資料表中融合成一個字串。 如果新資料表的字串名列資料表中包括和繼承的字串名同名的,那麼它的資料類型也必須和上面一樣與繼承字串匹配,並且這些字串定義會融合成一個。 不過,同名的繼承和新字串聲明可以聲明不同的約束:所有的繼承過來的約束以及聲明的約束都融合到一起,並且全部應用於新資料表。 如果新資料表為該字串明確的聲明了一個預設數值,那麼此預設數值覆蓋任何來自繼承字串聲明的預設值。 否則,任何為該字串聲明了預設數值的父資料表都必須聲明相同的預設,否則就會報告一個錯誤。
LIKE 子句聲明一個資料表,新資料表自動從這個資料表裡面繼承所有字串名, 他們的資料類型,以及非空約束。
和 INHERITS 不同,新資料表與原來的資料表之間在建立動作完畢之後是完全無關的。 在源資料表做的任何修改都不會施加到新資料表中,並且也不可能在掃瞄源資料表的時候包含新資料表的資料。
字串預設資料表達式只有在聲明了 INCLUDING DEFAULTS 之後才會包含進來。 預設是排除預設資料表達式,結果是新資料表中所有字串預設都是空。
這個可選的子句聲明新資料表中的行是否應該擁有賦予它們的 OID (對像標識)。 如果既沒有聲明 WITH OIDS 也沒有聲明 WITHOUT OIDS, 那麼預設值取決於配置參數 default_with_oids。 (如果新資料表從任何有 OID 的資料表繼承而來,那麼就算這條命令說了 WITHOUT OIDS, 也會強制 WITH OIDS。)
如果聲明或者隱含了 WITHOUT OIDS,新資料表就不會儲存 OID,並且插入資料行的時候也不會賦予 OID。 通常認為這麼做是值得的,因為這樣可以減少 OID 消耗並且推遲 32 位 OID 計數器的回捲。 一旦該計數器重疊,那麼就不能再假設 OID 的唯一,這樣它的實用性就大打折扣。 另外,把 OID 從一個資料表中排除還會減少在磁盤上儲存每行的空間,(在大多數機器上)每行減少 4 字元,因此也可以改進性能。
要在一個資料表建立之後從中刪除 OID,使用 ALTER TABLE。
列或資料表約束的可選名字。如果沒有聲明,則由系統生成一個名字。
字串不允許包含 NULL 數值。
該字串允許包含 NULL 數值。這是預設。
這個子句的存在只是為和那些非標準 SQL 資料庫兼容。 我們不建議在新應用中使用它。
UNIQUE 聲明一個規則,資料表示一個資料表裡的一個或者多個字串組合的分組只能包含唯一的數值。 資料表的唯一約束的行為和列約束的一樣,只不過多了跨多行的能力。
對於唯一約束的用途而言,系統認為 NULL 數值是不相等的。
每個唯一資料表約束都必須命名一個字串的集合,該集合必須和其它唯一約束命名字串集合或者該資料表定義的主鍵約束不同。 (否則就只是同樣的約束寫了兩次。)
主鍵約束資料表明資料表中的一個或者一些字串只能包含唯一(不重複)非 NULL 的數值。 從技術上講,PRIMARY KEY 只是 UNIQUE 和 NOT NULL 的組合,不過把一套字串標識為主鍵同時也體現了模式設計的元資料, 因為主鍵意味著其它資料表可以拿這套字串用做行的唯一標識。
一個資料表只能聲明一個主鍵,不管是作為字串約束還是資料表約束。
主鍵約束應該定義在同個資料表上的一個與其它唯一約束所定義的不同的字串集合上。
CHECK 約束聲明一個生成布爾結果的子句, 一次插入或者更新操作若想成功則裡面的新行或者被更新的行必須滿足這個條件。 值結果為真或者未知時成功。如果有任何插入或者更新的操作生成假的結果, 那麼都會拋出一個例外,而插入或更新動作不會影響資料庫。 聲明為字串約束的檢查約束應該只引用該字串的數值,而在資料表約束裡出現的資料表達式可以引用多個字串。
目前,CHECK 資料表達式不能包含子查詢也不能引用除目前行字串之外的變量。
這些子句聲明一個外鍵約束,外鍵約束要求新資料表中一列或者多列組成的組應該只包含匹配被引用的資料表 中對應引用的字串中的數值。 如果省略 refcolumn, 則使用 reftable 的主鍵。 被引用字串必須是被引用資料表中的唯一字串或者主鍵。
向引用字串插入的數值將使用給出的匹配類型與被引用資料表中被引用列的數值進行匹配。 有三種匹配類型:MATCH FULL, MATCH PARTIAL,和 MATCH SIMPLE,它也是預設匹配類型。 MATCH FULL 將不允許一個多字串外鍵的字串為 NULL,除非所有外鍵字串都為 NULL。 MATCH SIMPLE 允許某些外鍵字串為 NULL 而外鍵的其它部分不是 NULL。MATCH PARTIAL 還沒實現。
另外,當被參考字串中的資料改變的時候,那麼將對本資料表的字串中的資料執行某種操作。 ON DELETE 子句聲明當被參考資料表中的被參考行將被刪除的時候要執行的操作。 類似,ON UPDATE 子句聲明被參考資料表中被參考字串更新為新值的時候要執行的動作。 如果該行被更新,但被參考的字串實際上沒有變化,那麼就不會有任何動作。 除了 NO ACTION 檢查之外的參考動作不能推遲,即使該約束聲明為可以推遲的也如此。 下面是每個子句的可能的動作:
生成一個錯誤,資料表明刪除或者更新將產生一個違反外鍵約束的動作。 如果該約束是可推遲的,並且如果還存在任何引用行,那麼這個錯誤將在檢查約束的時候生成。 它是預設動作。
生成一個資料表明刪除或更新將導致違反外鍵約束的錯誤。 和 NO ACTION 一樣,只是動作不可推遲。
刪除任何引用了被刪除行的行,或者分別把引用行的字串值更新為被參考字串的新數值。
把引用行設置為 NULL。
把引用字串設置為它們的預設值。
如果被參考字串經常更新,那麼我們給外鍵字串增加一個索引可能是合適的, 這樣與外鍵字串相關聯的引用動作可以更有效地執行。
這兩個關鍵字設置該約束是否可推遲。一個不可推遲的約束將在每條命令之後馬上檢查。 可以推遲的約束檢查可以推遲到交易結尾(使用 SET CONSTRAINTS 命令)。 預設是 NOT DEFERRABLE。目前只有外鍵約束接受這個子句。所有其它約束類型都是不可推遲的。
如果約束是可推遲的,那麼這個子句聲明檢查約束的預設時間。 如果約束是 INITIALLY IMMEDIATE, 那麼每條語句之後就檢查它。這個是預設。如果約束是 INITIALLY DEFERRED,那麼只有在交易結尾才檢查它。 約束檢查的時間可以用 SET CONSTRAINTS 命令修改。
我們可以用 ON COMMIT 控制臨時資料表在交易結尾的行為。這三個選項是:
在交易結尾不發生任何特定的動作。這是預設行為。
臨時資料表的所有行在每次交易結尾都被刪除。實際上,在每次提交的時候都自動 TRUNCATE 。
在目前交易的結尾,臨時資料表將被刪除。
tablespace 是新資料表將要建立所在的資料表空間。 如果沒有聲明,將使用 default_tablespace,如果 default_tablespace 是空,那麼將使用資料庫的預設資料表空間。
這個子句允許選擇與一個 UNIQUE 或者 PRIMARY KEY 約束相關的所以建立時所在的資料表空間。 如果沒有提供這個子句,這個索引將在該資料表的同一個資料表空間中建立。
我們不建議在新應用中使用 OID,可能情況下,更好的選擇是使用一個 SERIAL 或者其它序列發生器做資料表的主鍵。 如果一個應用使用了 OID 標識資料表中的特定行,那麼我們建議在該資料表的 oid 字串上建立一個唯一約束,以確保該資料表的 OID 即使在計數器重疊之後也是唯一的。如果您需要一個整個資料庫範圍的唯一標識, 那麼就要避免假設 OID 是跨資料表唯一的,您可以用 tableoid 和行 OID 的組合來實現這個目的。
提示: 對那些沒有主鍵的資料表,我們不建議使用 WITHOUT OIDS, 因為如果既沒有 OID 又沒有唯一資料鍵字,那麼就很難標識特定的行。
PostgreSQL 自動為每個唯一約束和主鍵約束建立一個索引以確保唯一性。 因此,我們不必為主鍵字串明確的建立索引。 (參閱 CREATE INDEX 獲取更多訊息。)
唯一約束和主鍵在目前的實現裡是不能繼承的。 這樣,如果把繼承和唯一約束組合在一起會導致無法運轉。
一個資料表不能超過 1600 個字串。(實際上,實際的限制比這個更低, 因為還有遠祖長度限制。)
建立資料表 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_int (
vector INT[][]
);
為資料表 films 定義一個唯一資料表約束。 唯一資料表約束可以在資料表的一個或多個字串上定義:
CREATE TABLE films (
code char(5),
title varchar(40),
did decimal(3),
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)
);
在資料表空間 diskvol1 裡建立資料表 cinemas:
CREATE TABLE cinemas (
id serial,
name text,
location text
) TABLESPACE diskvol1;
CREATE TABLE 遵循 SQL-92 和 SQL:1999 的一個子集,一些例外情況在下面列出。
儘管 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。
NULL "約束"(實際上不是約束)是 PostgreSQL 對 SQL 標準的擴展, 包括它是為了和其它一些資料庫系統兼容(以及為了和 NOT NULL 約束對稱)。 因為它是任何字串的預設,所以它的出現只是噪音而已。
透過 INHERITS 子句的多重繼承是 PostgreSQL 語言的擴展。 SQL:1999(但不包括 SQL-92)使用不同的語法和語義定義了單繼承。 SQL:1999 風格的繼承還沒有在 PostgreSQL 中實現。