↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 8.1 已于 2010 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

CREATE TABLE

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 } ]
[ TABLESPACE tablespace ]

where column_constraint is:

[ 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 ]

and table_constraint is:

[ 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 对象,可用多种方式帮助定义表中允许的值集合。

定义约束有两种方式:表约束和列约束。列约束作为列定义的一部分定义。表约束则不绑定到特定列,并且可以涵盖多个列。每个列约束也都可以写成表约束;当约束只影响一列时,列约束只是一种书写上的方便。

参数

TEMPORARY or TEMP

如果指定该选项,表将创建为临时表。临时表会在会话结束时自动删除,或者也可在当前事务结束时删除(见下文 ON COMMIT)。在临时表存在期间,同名的现有永久表对当前会话不可见,除非使用带模式限定的名称引用它们。在临时表上创建的任何索引也都会自动成为临时索引。

可以选择在 TEMPORARY 或 TEMP 前写上 GLOBAL 或 LOCAL。这在 PostgreSQL 中没有任何区别,但参见兼容性。

table_name

要创建的表名(可选地带模式限定)。

column_name

要在新表中创建的列名。

data_type

列的数据类型。这可以包括数组说明符。有关 PostgreSQL 支持的数据类型的更多信息,请参见第 8 章。

DEFAULT default_expr

DEFAULT子句为其所在列定义的列指定默认数据值。该值可以是任何不含变量的表达式(不允许子查询,也不允许交叉引用当前表中的其他列)。默认表达式的数据类型必须与该列的数据类型匹配。

默认值表达式会用于任何未为该列指定值的插入操作。如果一列没有默认值,则默认值为 null。

INHERITS ( parent_table [, ... ] )

可选的 INHERITS 子句指定一组表,新表将自动从中继承所有列。

使用 INHERITS 会在新子表与其父表之间建立持久关系。对父表的模式修改通常也会传播到子表,且默认情况下,对父表的扫描会包含子表的数据。

如果同一列名出现在多个父表中,除非这些父表中该列的数据类型全部匹配,否则会报错。如果没有冲突,这些重复列会合并为新表中的单个列。如果新表的列名列表中包含一个同样来自继承的列名,其数据类型也必须与继承列匹配,并且列定义会合并为一个。不过,同名的继承列声明和新列声明不必指定完全相同的约束:来自任何声明的所有约束都会合并到一起,并且全部应用于新表。如果新表显式为该列指定了默认值,该默认值会覆盖继承声明中的任何默认值。否则,任何为该列指定默认值的父表都必须指定相同的默认值,否则会报错。

LIKE parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ]

LIKE 子句指定一个表,新表会自动从中复制所有列名、数据类型及其非空约束。

与 INHERITS 不同,新表和原表在创建完成后就完全脱钩了。对原表的修改不会应用到新表,也不可能在扫描原表时包含新表的数据。

只有指定INCLUDING DEFAULTS时,才会复制所复制列定义的默认表达式。默认行为是不包含默认表达式,因此新表的所有列将具有空默认值。

WITH OIDS
WITHOUT OIDS

这个可选子句指定新表的行是否应被分配 OID(对象标识符)。如果既没有指定WITH OIDS也没有指定WITHOUT OIDS,默认值取决于default_with_oids配置参数。(如果新表继承自任何具有 OID 的表,则会强制使用WITH OIDS,即使命令指定了WITHOUT OIDS也是如此。)

如果显式或隐式指定了WITHOUT OIDS,新表将不存储 OID,也不会为插入其中的行分配 OID。通常认为这样做是值得的,因为它会减少 OID 的消耗,从而推迟 32 位 OID 计数器回卷。一旦计数器回卷,就不能再假定 OID 是唯一的,这会大大降低它们的用途。此外,不在表中包含 OID 可以减少在磁盘上存储该表所需的空间,在大多数机器上每行可减少 4 字节,从而略微提高性能。

要在表创建之后删除 OID,可以使用ALTER TABLE。

CONSTRAINT constraint_name

列约束或表约束的可选名称。如果没有指定,系统会生成一个。

NOT NULL

该列不允许包含空值。

NULL

该列允许包含空值。这是默认情况。

该子句仅为兼容非标准 SQL 数据库而提供,不建议在新应用中使用。

UNIQUE (column constraint)
UNIQUE ( column_name [, ... ] ) (table constraint)

UNIQUE 约束指定表中一列或多列组成的一组只能包含唯一值。表级唯一约束的行为与列级唯一约束相同,只是它还能跨越多列。因此,该约束要求任意两行在这些列中至少有一列不同。

对于唯一约束,空值不被视为相等。

每个唯一表约束必须命名一组列,这组列不能与该表主键约束所命名的列集合相同。(否则它就只是把同一个约束列出了两次。)

PRIMARY KEY (column constraint)
PRIMARY KEY ( column_name [, ... ] ) (table constraint)

主键约束指定表的一个或多个列只能包含唯一(不重复)的非空值。从技术上讲,PRIMARY KEY只是UNIQUE和NOT NULL的组合,但把一组列标识为主键还为模式设计提供了元数据,因为主键意味着其他表可以依赖这组列作为行的唯一标识符。

一个表只能指定一个主键,无论是作为列约束还是表约束。

主键约束所命名的列集合应当不同于为同一表定义的任何唯一约束所命名的其他列集合。

CHECK (expression)

CHECK 子句指定一个产生布尔结果的表达式。要使插入或更新成功,新行或更新后的行必须满足该表达式。计算结果为 TRUE 或 UNKNOWN 的表达式视为成功。如果插入或更新操作中的任何一行得到 FALSE 结果,就会抛出错误异常,并且插入或更新不会修改数据库。作为列约束指定的检查约束只应引用该列的值,而出现在表约束中的表达式可以引用多个列。

当前,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)

这些子句指定外键约束,要求新表的一个或多个列组成的列组只能包含与被引用表某一行的被引用列值匹配的值。如果省略refcolumn列表,则使用reftable的主键。被引用列必须是被引用表中不可延迟的唯一约束或主键约束的列。请注意,不能在临时表和永久表之间定义外键约束。

插入到引用列中的值会按照给定的匹配类型,与被引用表及其被引用列中的值进行匹配。共有三种匹配类型:MATCH FULL、MATCH PARTIAL 和 MATCH SIMPLE(默认值)。MATCH FULL 不允许多列外键中的某一列为空,除非所有外键列都为空。MATCH SIMPLE 允许某些外键列为空而外键的其他部分不为空。MATCH PARTIAL 目前尚未实现。

此外,当被引用列中的数据发生变化时,会对本表列中的数据执行某些操作。ON DELETE子句指定删除被引用表中的被引用行时要执行的操作。同样,ON UPDATE子句指定将被引用表中的被引用列更新为新值时要执行的操作。如果行被更新,但被引用列实际上没有变化,则不执行任何操作。除NO ACTION检查以外的引用操作都不能延迟,即使该约束声明为可延迟也是如此。每个子句可以指定以下操作:

NO ACTION

产生错误,指出删除或更新会违反外键约束。如果该约束被延迟,则会在约束检查时仍存在引用行的情况下产生这个错误。这是默认操作。

RESTRICT

产生错误,指出删除或更新会违反外键约束。这与NO ACTION相同,但检查不能延迟。

CASCADE

分别删除任何引用已删除行的行,或将引用列的值更新为被引用列的新值。

SET NULL

将引用列设置为空值。

SET DEFAULT

将引用列设置为其默认值。(如果默认值不为空,则被引用表中必须存在与这些默认值匹配的行,否则操作会失败。)

如果被引用列经常变化,可以考虑在外键列上添加索引,使与该外键列关联的引用动作能够更高效地执行。

DEFERRABLE
NOT DEFERRABLE

这控制约束是否可以延迟。不可延迟的约束会在每条命令之后立即检查。可延迟约束的检查可以推迟到事务结束(使用SET CONSTRAINTS命令)。NOT DEFERRABLE是默认值。目前,只有外键约束接受此子句。所有其他类型的约束都不可延迟。

INITIALLY IMMEDIATE
INITIALLY DEFERRED

如果约束可延迟,则此子句指定检查约束的默认时间。如果约束为INITIALLY IMMEDIATE,则在每条语句之后检查。这是默认值。如果约束为INITIALLY DEFERRED,则仅在事务结束时检查。可以使用SET CONSTRAINTS命令更改约束检查时间。

ON COMMIT

可以使用 ON COMMIT 控制临时表在事务块结束时的行为。三种选项如下:

PRESERVE ROWS

在事务结束时不执行任何特殊操作。这是默认行为。

DELETE ROWS

临时表中的所有行都会在每个事务块结束时删除。实际上,每次提交时都会自动执行一次TRUNCATE。

DROP

在当前事务块结束时删除临时表。

TABLESPACE tablespace

tablespace是要创建新表的表空间名称。如果未指定,则使用default_tablespace;如果default_tablespace为空字符串,则使用数据库的默认表空间。

USING INDEX TABLESPACE tablespace

该子句允许选择与 UNIQUE 或 PRIMARY KEY 约束相关联的索引要创建在哪个表空间中。若未指定,则使用default_tablespace;如果 default_tablespace为空字符串,则使用数据库的默认表空间。

注解

不建议在新应用中使用 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 <> '')
);

创建一个带二维数组列的表:

CREATE TABLE array_int (
    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)
);

在表空间diskvol1中创建表cinemas:

CREATE TABLE cinemas (
        id serial,
        name text,
        location text
) TABLESPACE diskvol1;

兼容性

CREATE TABLE 命令符合 SQL 标准,但有下列例外。

临时表

尽管 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“约束”

NULL “约束”(实际上并不是约束)是 PostgreSQL 对 SQL 标准的扩展;提供它是为了与其他一些数据库系统兼容(以及与 NOT NULL 约束保持对称)。由于它本来就是任意列的默认情况,所以它的存在只是噪声。

继承

通过 INHERITS 子句实现的多重继承是 PostgreSQL 的语言扩展。SQL:1999 及后续标准使用不同的语法和语义定义了单继承。PostgreSQL 尚不支持 SQL:1999 风格的继承。

零列表

PostgreSQL 允许创建没有列的表(例如 CREATE TABLE foo();)。这是对 SQL 标准的扩展,标准不允许零列的表。零列的表本身并不十分有用,但若禁止它们,就会让 ALTER TABLE DROP COLUMN 出现奇怪的特殊情况,因此忽略这一规范限制看起来更整洁。

对象 ID

PostgreSQL 的 OID 概念不是标准的概念。

表空间

PostgreSQL 的表空间概念不是标准的一部分。因此,TABLESPACE 和 USING INDEX TABLESPACE 子句都是扩展。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。