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 前面放上 GLOBAL 或者
LOCAL。 這樣對 PostgreSQL
沒有任何區別,可以參閱
Compatibility [create_table(7)]。
預設表示式將被用於任何未宣告該欄位數值的插入操作。
如果欄位上沒有預設值,那麼預設是
NULL。
和 INHERITS
不同,新表與繼承過來的表之間在建立動作完畢之後是完全無關的。
插入新表的資料不會在父表中表現出來。
欄位預設表示式只有在聲明瞭
INCLUDING DEFAULTS
之後才會繼承過來。
預設是排除預設表示式。
宣告 WITHOUT OIDS
允許使用者禁止為行或者表生成
OID。
這麼做對大表是值得的,因為這樣可以減少
OID 消耗並且推遲 32 位 OID
計數器的消耗。
一旦該計數器重疊,那麼就不能再假設
OID
的唯一,這樣它的實用性就大打折扣。
宣告 WITHOUT OIDS
還會減少在磁碟上儲存每行的空間,每行減少
4
位元組,因此也可以改進效能。
這個子句的存在只是為和那些非標準
SQL 資料庫相容。
我們不建議在新應用中使用它。
對於唯一約束的用途而言,系統認為
NULL
數值是不相等的。
每個唯一表約束都必須命名一個欄位的集合,該集合必須和其它唯一約束命名欄位集合或者該表定義的主鍵約束不同。
(否則就只是同樣的約束寫了兩次。)
一個表只能宣告一個主鍵,不管是作為欄位約束還是表約束。
主鍵約束應該定義在同個表上的一個與其它唯一約束所定義的不同的欄位集合上。
目前,CHECK
表示式不能包含子查詢也不能引用除當前行欄位之外的變數。
向這些欄位插入的數值將使用給出的匹配型別與參考表中的參考列中的數值進行匹配。
有三種匹配型別:MATCH
FULL, MATCH PARTIAL,和 MATCH
SIMPLE,它也是預設匹配型別。
MATCH FULL
將不允許一個多欄位外來鍵的欄位為
NULL,除非所有外來鍵欄位都為
NULL。 MATCH SIMPLE
允許某些外來鍵欄位為
NULL
而外來鍵的其它部分不是
NULL。MATCH PARTIAL 還沒實現。
另外,當被參考欄位中的資料改變的時候,那麼將對本表的欄位中的資料執行某種操作。
ON DELETE
子句聲明當被參考表中的被參考行將被刪除的時候要執行的操作。
類似,ON UPDATE
子句宣告被參考表中被參考欄位更新為新值的時候要執行的動作。
如果該行被更新,但被參考的欄位實際上沒有變化,那麼就不會有任何動作。
下面是每個子句的可能的動作:
如果主鍵欄位經常更新,那麼我們給
REFERENCES
欄位增加一個索引可能是合適的,這樣與
REFERENCES 欄位相關聯的 NO ACTION
和 CASCADE
動作可以更有效地執行。
建立表 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 |