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带来很奇怪的情况,所以,这个时候忽视标准的限制好想很清楚。