CREATE TABLE

Name

CREATE TABLE  --  定义一个新表

Synopsis

CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name (
    { column_name data_type [ DEFAULT default_expr ] [ column_constraint [, ... ] ]
    | table_constraint }  [, ... ]
)
[ INHERITS ( parent_table [, ... ] ) ]
[ WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]

这里 column_constraint 可以是:

[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | UNIQUE | PRIMARY KEY |
  CHECK (expression) |
  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL ]    [ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

而 table_constraint 可以是:

[ CONSTRAINT constraint_name ]
{ UNIQUE ( column_name [, ... ] ) |  PRIMARY KEY ( column_name [, ...
] ) |
  CHECK ( expression ) |
  FOREIGN KEY ( column_name [, ...
] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
    [ MATCH FULL | MATCH PARTIAL ] [ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
  

描述

CREATE TABLE 将在当前数据库创建一个新的, 初始为空的表.该表将由发出此命令的用户所有.

如果给出了模式名(比如,CREATE TABLE myschema.mytable ...), 那么表是在指定模式中创建的.否则它在当前模式中创建 (在搜索路径前面的那个;参阅 CURRENT_SCHEMA()). TEMP(临时)表存在于一个特殊的模式里,因此创建 TEMP 表的时候不能 给出模式名.表名字必需和同一模式中其他表,序列,索引或者视图相区别.

CREATE TABLE 还自动创建一个数据类型, 该数据类型代表对应该表一行的元组类型(结构类型). 因此,表不能和同模式中的现有数据类型同名.

一个表的字段数不能超过 1600.(实际上,真正的限制比这低, 因为还有元组长度的约束).

可选的约束子句声明约束(或者测试),新行或者更新的行必须满足 这些约束才能成功插入或更新.约束是一个命名的规则∶ 它是一个 SQL 对象,它通过对发生在表上的插入,更新或者删除操作 的结果进行限制来协助我们定义有效的数值集合.

定义约束又两种方法∶表约束和列约束.一个列约束是作为 一个列定义的一部分定义的.而表约束并不和某个列绑在一起, 它可以作用于多于一个列上.每个列约束也可以写成表约束; 如果某个约束只影响一个列,那么列约束只是符号上的简洁方式而已.

参数

[LOCAL] TEMPORARY[LOCAL] TEMP

如果声明了此参数,则该表创建为临时表.临时表在会话结束时自动删除, 或者是(可选)在当前事务的结尾(参阅下面的 ON COMMIT). 现有同名永久表在临时表存在期间在本会话过程中是不可见的, 除非它们是用模式修饰的名字引用的. 任何在临时表上创建的索引也都会自动删除.

关键字 LOCAL 是可选的.又见 兼容性.

table_name

要创建的表的名字(可以用模式修饰).

column_name

在新表中要创建的字段名字.

data_type

该字段的数据类型.它可以包括数组说明符.请参考 用户手册获取有关数据类型和数组的更多信息.

DEFAULT default_expr

DEFAULT 子句给它所出现的字段一个缺省数值. 该数值可以是任何不含变量的表达式(不允许使用子查询和对本 表中的其它字段的交叉引用).缺省表达式的数据类型必须和字段类型匹配.

缺省表达式将被用于任何未声明该字段数值的插入操作. 如果字段上没有缺省值,那么缺省是 NULL.

INHERITS ( parent_table [, ... ] )

可选的 INHERITS 子句声明一列表,这个新表自动从这列表 中继承所有字段.如果在多于一个父表中存在同名的字段, 那么就会报告一个错误,除非这些字段的数据类型在每个父表里都是匹配的. 如果没有冲突,那么重复的字段在新表中融合成一个字段. 如果新表的字段名列表中包括和继承的字段同名的,那么它的数据类型也 必须和上面一样与继承字段匹配,并且这些字段定义会融合成一个. 不过,同名的继承和新字段声明可以声明不同的约束∶所有的继承过来的 约束以及声明的约束都融合到一起,并且全部应用于新表. 如果新表为该字段明确的声明了一个缺省数值,那么此缺省数值覆盖任何 来自继承字段声明的缺省值.否则,任何为该字段声明了缺省数值的 父表都必须声明相同的缺省,否则就会报告一个错误.

WITH OIDSWITHOUT OIDS

这个可选的子句声明新表中的行是否应该拥有赋予它们的 OID (对象标识). 缺省是有 OID.(如果新表从任何有 OID 的表继承而来,那么就算 这条命令说了 WITHOUT OIDS,也会强制 WITH OIDS.)

声明 WITHOUT OIDS 允许用户禁止为行或者表生成 OID. 这么做对大表是值得的,因为这样可以减少 OID 消耗并且推迟 32 位 OID 计数器的消耗.一旦该计数器重叠,那么就不能再假设 OID 的唯一,这样它的实用性就大打折扣.

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 只是 UNIQUENOT NULL 的组合,不过把一套字段标识为主键同时也 体现了模式设计的元数据,因为主键意味着其它表可以拿这套字段 用做行的唯一标识.

一个表只能声明一个主键,不管是作为字段约束还是表约束.

主键约束应该定义在同个表上的一个与其它唯一约束所定义的不同的字段集合上.

CHECK (expression)

CHECK 约束声明一个完整性约束或者测试, 一次插入或者更新操作若想成功则必须满足这个条件. 每个约束都必须是一个生成布尔结果的表达式.一个在字段定义中出现的

目前,CHECK 表达式不能包含子查询或者 引用除本行字段之外的变量.

REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ] (column constraint)
FOREIGN KEY ( column [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ] (table constraint)

REFERENCES 列约束声明一个由新表中一列或者多列 组成的组应该只包含匹配引用的表 reftable 中对应引用的 字段 refcolumn 中的数值. 如果省略 refcolumn, 则使用 reftable 的主键. 被引用字段必须是被引用表中的唯一字段或者主键.

向这些字段增加的数值将使用给出的匹配类型与参考表中的参考列 中的数值进行匹配.有三种匹配类型∶MATCH FULLMATCH PARTIAL,和一种缺省匹配类型(如果没有声明 匹配类型的话).MATCH FULL 将不允许一个多字段外键的 字段为 NULL,除非所有外键字段都为 NULL.缺省匹配类型允许某些 外键字段为 NULL 而外键的其它部分不是 NULL.MATCH PARTIAL 还没实现.

另外,当被参考字段中的数据改变的时候,那么将对本表的字段中的数据 执行某种操作.ON DELETE 子句声明当被参考表中的 被参考行将被删除的时候要执行的操作.类似,ON UPDATE 子句声明被参考表中被参考字段更新为新值的时候要执行的动作. 如果该行被更新,但被参考的字段实际上没有变化,那么就不会有任何动作. 下面是每个子句的可能的动作∶

NO ACTION

生成一个错误,表明删除或者更新将产生一个违反外键约束的动作. 它是缺省动作.

RESTRICT

NO ACTION 一样.

CASCADE

删除任何引用了被删除行的行,或者分别把引用行的字段值更新为 被参考字段的新数值.

SET NULL

把引用行数值设置为 NULL.

SET DEFAULT

把引用列的数值设置为它们的缺省值.

如果主键字段经常更新,那么我们给 REFERENCES 字段增加一个索引可能是合适的,这样与 REFERENCES 字段 相关联的 NO ACTIONCASCADE 动作可以更有效地执行.

DEFERRABLENOT DEFERRABLE

这两个关键字设置该约束是否可推迟.一个不可推迟的约束将在每条命令之后 马上检查.可以推迟的约束检查可以推迟到事务结尾 (使用 SET CONSTRAINTS 命令). 缺省是 NOT DEFERRABLE.目前只有外键约束 接受这个子句.所有其它约束类型都是不可推迟的.

INITIALLY IMMEDIATE or INITIALLY DEFERRED

如果约束是可推迟的,那么这个子句声明检查约束的缺省时间. 如果约束是 INITIALLY IMMEDIATE, 那么每条语句之后就检查它.这个是缺省.如果约束是 INITIALLY DEFERRED,那么只有在事务结尾才检查它. 约束检查的时间可以用 SET CONSTRAINTS 命令修改.

ON COMMIT

我们可以用 ON COMMIT 控制临时表在事务块 结尾的行为。这三个选项是:

PRESERVE ROWS

在事务结尾不发生任何特定的动作。这是缺省行为。

DELETE ROWS

临时表的所有行在每次事务结尾都被删除。实际上,在每次提交的 时候都自动 TRUNCATE

DROP

在当前事务块的结尾,临时表将被删除。

诊断

CREATE

如果表成功创建,返回此信息.

ERROR

如果表创建失败返回这条信息.通常它还带着一些描述性文本, 比如∶ ERROR: Relation 'table' already exists,这个错误出现在运行时 -- 如果 声明的表已经在数据库中存在了.

注意

例子

创建表 filmsdistributors

CREATE TABLE films (
    code        CHARACTER(5) CONSTRAINT firstkey PRIMARY KEY,
    title       CHARACTER VARYING(40) NOT NULL,
    did         DECIMAL(3) NOT NULL,
    date_prod   DATE,
    kind        CHAR(10),
    len         INTERVAL HOUR TO MINUTE
);

CREATE TABLE distributors (
     did    DECIMAL(3) 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         DECIMAL(3),
    date_prod   DATE,
    kind        VARCHAR(10),
    len         INTERVAL HOUR TO MINUTE,
    CONSTRAINT production UNIQUE(date_prod)
);

定义一个检查列约束∶

CREATE TABLE distributors (
    did     DECIMAL(3) CHECK (did > 100),
    name    VARCHAR(40)
);

定义一个检查表约束∶

CREATE TABLE distributors (
    did     DECIMAL(3),
    name    VARCHAR(40)
    CONSTRAINT con1 CHECK (did > 100 AND name <> '')
);

为表 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 code_title PRIMARY KEY(code,title)
);

为表 distributors 定义一个主键约束. 下面两个例子是等效的,第一个例子使用了表约束语法, 第二个使用了列约束表示法.

CREATE TABLE distributors (
    did     DECIMAL(3),
    name    CHAR VARYING(40),
    PRIMARY KEY(did)
);

CREATE TABLE distributors (
    did     DECIMAL(3) 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     DECIMAL(3) CONSTRAINT no_null NOT NULL,
    name    VARCHAR(40) NOT NULL
);

name 字段定义一个唯一约束∶

CREATE TABLE distributors (
    did     DECIMAL(3),
    name    VARCHAR(40) UNIQUE
);

上面的和下面这样作为一个表约束声明是一样的∶

CREATE TABLE distributors (
    did     DECIMAL(3),
    name    VARCHAR(40),
    UNIQUE(name)
);

兼容性

CREATE TABLE 遵循 SQL92 和 SQL99 的一个子集 的中间状态,一些例外情况在下面和上面的诊断中列出.

临时表

除了局部临时表之外,SQL92 还定义了 CREATE GLOBAL TEMPORARY TABLE 语句. 全局临时表也可以在其它会话中可见.

对于临时表,有一个可选的 ON COMMIT 子句∶

CREATE { GLOBAL | LOCAL } TEMPORARY TABLE table ( ... ) [ ON COMMIT {
DELETE | PRESERVE } ROWS ]

ON COMMIT 子句表明该临时表在执行 COMMIT 的时候是否应该清空行. 如果省略了 ON OMMIT 子句,SQL92 声明缺省是 ON COMMIT DELETE ROWS.不过, PostgreSQL 的行为总是类似 ON COMMIT PRESERVE ROWS

NULL "约束"

NULL "约束"(实际上不是约束) 是 PostgreSQL 对 SQL92 的扩展, 包括它是为了和其它一些 RDBMS 兼容(以及为了和 NOT NULL 约束对称).因为它是任何字段的缺省,所以它的出现只是噪音而已.

断言

断言是一种特殊类型的完整性约束,它和其它约束共享相同的名字空间. 不过,断言和约束不同的是,它不一定依赖于某个特定的表,因此 SQL92 提供了 CREATE ASSERTION 语句作为定义 约束的一个可选的方法∶

CREATE ASSERTION name CHECK ( condition )

PostgreSQL 目前还没有实现断言.

继承

通过 INHERITS 子句的多重继承是 PostgreSQL 语言的扩展. SQL99(但不包括 SQL92)使用不同的语法和语义定义了单继承. SQL99 风格的继承还没有在 PostgreSQL 中实现.

对象 ID

PostgreSQL 的 OID 的概念不是标准.

又见

ALTER TABLE, DROP TABLE