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

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 10 已于 2022 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

CREATE TABLE

CREATE TABLE — 定义一个新表

大纲

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ PARTITION BY { RANGE | LIST } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
    OF type_name [ (
  { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]
    | table_constraint }
    [, ... ]
) ]
[ PARTITION BY { RANGE | LIST } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
    PARTITION OF parent_table [ (
  { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ]
    | table_constraint }
    [, ... ]
) ] FOR VALUES partition_bound_spec
[ PARTITION BY { RANGE | LIST } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

其中column_constraint为:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
  NULL |
  CHECK ( expression ) [ NO INHERIT ] |
  DEFAULT default_expr |
  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
  UNIQUE index_parameters |
  PRIMARY KEY index_parameters |
  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 ]
{ CHECK ( expression ) [ NO INHERIT ] |
  UNIQUE ( column_name [, ... ] ) index_parameters |
  PRIMARY KEY ( column_name [, ... ] ) index_parameters |
  EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
  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 ]

而like_option为:

{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }

而partition_bound_spec为:

IN ( { numeric_literal | string_literal | TRUE | FALSE | NULL } [, ...] ) |
FROM ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] )
  TO ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] )

UNIQUE、PRIMARY KEY和EXCLUDE约束中的index_parameters为:

[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]

EXCLUDE约束中的exclude_element为:

{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

描述

CREATE TABLE 将在当前数据库中创建一个新的、初始为空的表。该表归发出该命令的用户所有。

如果给出了模式名(例如 CREATE TABLE myschema.mytable ...),则表将在指定模式中创建。否则,它将在当前模式中创建。临时表存在于一个特殊模式中,因此创建临时表时不能给出模式名。表名必须与同一模式中任何其他表、序列、索引、视图或外部表的名称不同。

CREATE TABLE 还会自动创建一种数据类型,用以表示与该表一行对应的复合类型。因此,表名不能与同一模式中任何已有数据类型同名。

可选的约束子句指定插入或更新要成功时,新行或更新后的行必须满足的约束(测试)。约束是一种 SQL 对象,可用多种方式帮助定义表中允许的值集合。

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

要创建表,必须分别对所有列类型或 OF 子句中的类型拥有 USAGE 权限。

参数

TEMPORARY 或 TEMP #

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

自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE。

可以在 TEMPORARY 或 TEMP 前写 GLOBAL 或 LOCAL。这在当前的 PostgreSQL 中没有区别,而且已弃用;见下文兼容性。

UNLOGGED #

如果指定该选项,表将创建为不记录 WAL 的表。写入不记录 WAL 的表的数据不会写入预写式日志(见第 30 章),因此它们比普通表快得多。不过,它们不具备崩溃安全性:在崩溃或非正常关闭后,不记录 WAL 的表会被自动截断。不记录 WAL 的表的内容也不会复制到备库。在不记录 WAL 的表上创建的任何索引也都会自动成为不记录 WAL 的。

IF NOT EXISTS

如果已存在同名关系,则不抛出错误,而是发出一条提示。注意,这并不保证现有关系与本应创建出的关系有任何相似之处。

table_name

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

OF type_name

创建一个类型化表,其结构取自指定的复合类型(名称可以带模式限定)。类型化表与其类型绑定;例如,如果删除该类型(使用DROP TYPE ... CASCADE),该表也会被删除。

创建类型化表时,列的数据类型由底层复合类型决定,不由CREATE TABLE命令指定。不过,CREATE TABLE命令可以为表添加默认值和约束,并指定存储参数。

PARTITION OF parent_table FOR VALUES partition_bound_spec #

将表创建为指定父表的一个分区。

partition_bound_spec必须与父表的分区方法和分区键相对应,且不得与该父表的任何现有分区重叠。带有IN的形式用于列表分区,带有FROM和TO的形式用于范围分区。

为partition_bound_spec指定的每个值都是字面值、NULL、MINVALUE或MAXVALUE。每个字面值必须是可转换为相应分区键列类型的数值常量,或者是对该类型有效的字符串字面量。

在创建列表分区时,可以指定 NULL,表示该分区允许分区键列为 NULL。但是,对于给定的父表,这样的列表分区不能多于一个。NULL 不能用于范围分区。

创建范围分区时,由 FROM 指定的下界是包含边界,而由 TO 指定的上界是不包含边界。也就是说,FROM 列表中指定的值是该分区相应分区键列的有效值,而 TO 列表中的值不是。请注意,必须根据按行比较的规则来理解这一点(第 9.23.5 节)。例如,给定 PARTITION BY RANGE (x,y),分区边界 FROM (1, 2) TO (3, 4) 允许 x=1 且任意 y>=2,x=2 且任意非 NULL 的 y,以及 x=3 且任意 y<4。

在创建范围分区时,可以使用特殊值 MINVALUE 和 MAXVALUE 表示该列值没有下界或上界。例如,使用 FROM (MINVALUE) TO (10) 定义的分区允许任何小于 10 的值,而使用 FROM (10) TO (MAXVALUE) 定义的分区允许任何大于或等于 10 的值。

在创建涉及多列的范围分区时,将 MAXVALUE 用作下界的一部分、将 MINVALUE 用作上界的一部分也可能是有意义的。例如,使用 FROM (0, MAXVALUE) TO (10, MAXVALUE) 定义的分区允许第一个分区键列大于 0 且小于或等于 10 的所有行。类似地,使用 FROM ('a', MINVALUE) TO ('b', MINVALUE) 定义的分区允许第一个分区键列以“a”开头的所有行。

请注意,如果 MINVALUE 或 MAXVALUE 用于分区边界中的某一列,则后续所有列都必须使用相同的值。例如,(10, MINVALUE, 0) 不是有效边界;应写成 (10, MINVALUE, MINVALUE)。

还要注意,某些元素类型(如 timestamp)具有“无穷大”的概念,那只是另一种可存储的值。这不同于 MINVALUE 和 MAXVALUE,后两者并非可存储的实际值,而只是表示值无界的方式。MAXVALUE 可以视为大于任何其他值,包括“无穷大”;MINVALUE 可以视为小于任何其他值,包括“负无穷大”。因此,范围 FROM ('infinity') TO (MAXVALUE) 并不是空范围;它只允许存储一个值 — “无穷大”。

分区必须具有与其所属分区表相同的列名和类型。如果父表指定了WITH OIDS,则所有分区都必须有 OID;父表的 OID 列会像其他列一样被所有分区继承。修改分区表的列名或类型,或者添加或删除 OID 列,都会自动传播到所有分区。每个分区都会自动继承CHECK约束,但单个分区可以指定额外的CHECK约束;如果额外约束与父表中约束的名称和条件相同,则会与父表约束合并。可以为每个分区分别指定默认值。但请注意,通过分区表插入元组时不会应用分区的默认值。

插入分区表的行会自动路由到正确的分区。如果不存在合适的分区,将发生错误。此外,如果由于新的分区键值,更新给定分区中的行需要将其移到另一个分区,也会发生错误。

TRUNCATE 等通常会影响一个表及其所有继承子表的操作,会级联到所有分区,但也可以在单个分区上执行。请注意,使用DROP TABLE删除分区需要在父表上获取ACCESS EXCLUSIVE锁。

column_name

要在新表中创建的列名。

data_type

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

COLLATE collation

COLLATE子句为列指定排序规则(该列必须属于支持排序规则的数据类型)。如果未指定,则使用列数据类型的默认排序规则。

INHERITS ( parent_table [, ... ] )

可选的 INHERITS 子句指定一组表,新表将自动从中继承所有列。父表可以是普通表或外部表。

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

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

CHECK 约束基本上也按与列相同的方式合并:如果多个父表和/或新表定义中包含同名的 CHECK 约束,则这些约束必须拥有相同的检查表达式,否则会报错。同名且表达式相同的约束将合并为一份。父表中标记为 NO INHERIT 的约束不会被考虑。注意,新表中未命名的 CHECK 约束永远不会被合并,因为系统总会为它选择一个唯一名称。

列的 STORAGE 设置也会从父表复制过来。

如果父表中的列是标识列,则该属性不会被继承。若需要,可将子表中的列声明为标识列。

PARTITION BY { RANGE | LIST } ( { column_name | ( expression ) } [ opclass ] [, ...] )

可选的PARTITION BY子句指定表的分区策略。这样创建的表称为分区表。括号中的列或表达式列表构成该表的分区键。使用范围分区时,分区键可以包含多个列或表达式(最多 32 个,但构建PostgreSQL时可以更改此限制);但对于列表分区,分区键必须由单个列或表达式组成。如果创建分区表时未指定 B-树操作符类,则使用该数据类型的默认 B-树操作符类。如果不存在,将报告错误。

分区表被划分为多个子表(称为分区),它们使用单独的 CREATE TABLE 命令创建。分区表本身为空。插入到该表的数据行会根据分区键中列或表达式的值被路由到相应分区。如果没有现有分区与新行中的值匹配,就会报错。

分区表不支持UNIQUE、PRIMARY KEY、EXCLUDE或FOREIGN KEY约束;不过,可以在单个分区上定义这些约束。

LIKE source_table [ like_option ... ]

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

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

只有指定INCLUDING DEFAULTS时,才会复制所复制列定义的默认表达式。默认行为是不包含默认表达式,因此新表中所复制列的默认值将为 NULL。请注意,复制调用数据库修改函数(例如nextval)的默认值,可能会在原表和新表之间创建功能性关联。

只有指定INCLUDING IDENTITY时,才会复制所复制列定义中的标识规范。新表的每个标识列都会创建一个新序列,与旧表关联的序列分开。

非空约束始终会复制到新表。只有指定INCLUDING CONSTRAINTS时,才会复制CHECK约束。列约束和表约束之间不作区分。

指定INCLUDING STATISTICS时,扩展统计信息会复制到新表。

只有指定INCLUDING INDEXES时,才会在新表上创建原表的索引、PRIMARY KEY、UNIQUE和EXCLUDE约束。新索引和约束的名称按照默认规则选择,与原名称无关。(此行为可以避免新索引可能发生名称重复错误。)

只有指定INCLUDING STORAGE时,才会复制所复制列定义的STORAGE设置。默认行为是不包含STORAGE设置,因此新表中复制的列使用其类型特定的默认设置。有关STORAGE设置的更多信息,请参见第 67.2 节。

只有指定INCLUDING COMMENTS时,才会复制所复制列、约束和索引的注释。默认行为是不包含注释,因此新表中复制的列和约束没有注释。

INCLUDING ALL是INCLUDING COMMENTS INCLUDING CONSTRAINTS INCLUDING DEFAULTS INCLUDING IDENTITY INCLUDING INDEXES INCLUDING STATISTICS INCLUDING STORAGE的简写形式。

请注意,与INHERITS不同,LIKE复制的列和约束不会与同名的列和约束合并。如果显式指定了相同的名称,或在另一个LIKE子句中指定了相同的名称,则会报错。

LIKE 子句也可用于从视图、外部表或复合类型复制列定义。不适用的选项(例如从视图复制 INCLUDING INDEXES)会被忽略。

CONSTRAINT constraint_name

列约束或表约束的可选名称。如果约束被违反,错误消息中会包含该约束名,因此诸如 col must be positive 这样的约束名可以向客户端应用传达有用的约束信息。(若约束名中包含空格,则需要用双引号指定。)如果未指定约束名,系统会生成一个。

NOT NULL

该列不允许包含空值。

NULL

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

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

CHECK ( expression ) [ NO INHERIT ]

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

当前,CHECK 表达式不能包含子查询,也不能引用当前行的列之外的变量(参见第 5.3.1 节)。可以引用系统列 tableoid,但不能引用其他系统列。

标记为 NO INHERIT 的约束不会传播到子表。

当一个表有多个 CHECK 约束时,在检查完 NOT NULL 约束之后,会按名称的字母顺序对每一行进行检查。(9.5 之前的 PostgreSQL 版本并不保证 CHECK 约束的特定触发顺序。)

DEFAULT default_expr

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

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

GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]

该子句将列创建为标识列。它会隐式附带一个序列,并且在新插入的行中,该列会自动取得分配给它的序列值。这种列会隐式带有 NOT NULL 约束。

ALWAYS和BY DEFAULT子句决定在INSERT语句中序列值与用户指定值的优先关系。如果选择了 ALWAYS,则仅当 INSERT 语句指定 OVERRIDING SYSTEM VALUE 时才接受用户指定的值。如果选择了 BY DEFAULT,则用户指定的值优先。有关详细信息,请参阅INSERT。(在 COPY 命令中,无论此设置如何,始终使用用户指定的值。)

可选的sequence_options子句可用于覆盖序列的选项。详情见CREATE SEQUENCE。

UNIQUE(列约束)
UNIQUE ( column_name [, ... ] )(表约束)

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

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

每个唯一约束都应引用一组列,这组列应不同于该表上任何其他唯一约束或主键约束所引用的列集合。(否则,冗余的唯一约束将被丢弃。)

PRIMARY KEY(列约束)
PRIMARY KEY ( column_name [, ... ] )(表约束)

PRIMARY KEY 约束指定表的一列或多列只能包含唯一(不重复)且非空的值。无论作为列约束还是表约束,一个表都只能指定一个主键。

主键约束所引用的列集合应不同于同一表上定义的任何唯一约束所引用的列集合。(否则,该唯一约束是冗余的,会被丢弃。)

PRIMARY KEY 强制的数据约束与 UNIQUE 和 NOT NULL 的组合相同。不过,将一组列标识为主键还会为模式设计提供元数据,因为主键意味着其他表可以将这组列作为行的唯一标识符来依赖。

添加 PRIMARY KEY 约束会自动在约束所用的列或列组上创建唯一 B-树索引。

EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] #

EXCLUDE 子句定义一个排他约束。它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,这些比较不会全部返回 TRUE。如果所有指定操作符都测试相等,这就等价于 UNIQUE 约束,尽管普通唯一约束会更快。不过,排他约束可以指定比简单相等更一般的约束。例如,你可以通过使用 && 操作符来指定一个约束,使表中不存在两个包含重叠圆的行(见第 8.8 节)。

排他约束通过索引实现,因此每个指定的操作符都必须与索引访问方法index_method的适当操作符类关联(见第 11.9 节)。这些操作符必须满足交换律。每个exclude_element都可以选择指定操作符类和/或排序选项;详见CREATE INDEX。

访问方法必须支持 amgettuple(见第 60 章);目前这意味着不能使用 GIN。虽然允许,但在排他约束上使用 B-树或 hash 索引意义不大,因为它们做不到比普通唯一约束更好的事情。因此,实践中访问方法总是 GiST 或 SP-GiST。

predicate 允许你只在表的一个子集上指定排他约束;在内部,这会创建一个部分索引。注意,谓词周围的圆括号是必需的。

REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ](列约束)
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ](表约束)

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

插入到引用列中的值会按照给定的匹配类型,与被引用表及其被引用列中的值进行匹配。共有三种匹配类型:MATCH FULL、MATCH PARTIAL 和 MATCH SIMPLE(默认值)。MATCH FULL 不允许多列外键中的某一列为空,除非所有外键列都为空;如果它们都为空,则不要求该行在被引用表中有匹配行。MATCH SIMPLE 允许任意外键列为空;如果其中任何一列为空,则不要求该行在被引用表中有匹配行。MATCH PARTIAL 目前尚未实现。(当然,可以对引用列应用 NOT NULL 约束,以防止出现这些情况。)

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

NO ACTION

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

RESTRICT

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

CASCADE

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

SET NULL

将引用列设置为空值。

SET DEFAULT

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

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

DEFERRABLE
NOT DEFERRABLE

这控制约束是否可以延迟。不可延迟的约束会在每条命令之后立即检查。可延迟约束的检查可以推迟到事务结束(使用SET CONSTRAINTS命令)。NOT DEFERRABLE是默认值。目前,只有UNIQUE、PRIMARY KEY、EXCLUDE和REFERENCES(外键)约束接受此子句。NOT NULL和CHECK约束不可延迟。请注意,不能将可延迟约束用作包含ON CONFLICT DO UPDATE子句的INSERT语句中的冲突仲裁器。

INITIALLY IMMEDIATE
INITIALLY DEFERRED

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

WITH ( storage_parameter [= value] [, ... ] )

该子句为表或索引指定可选的存储参数;详情见存储参数。表的WITH子句还可以包含OIDS=TRUE(或仅写OIDS),以指定为新表的行分配 OID(对象标识符);也可以包含OIDS=FALSE,以指定行不应具有 OID。如果未指定OIDS,默认设置取决于default_with_oids配置参数。(如果新表继承自任何具有 OID 的表,则会强制使用OIDS=TRUE,即使命令指定了OIDS=FALSE也是如此。)

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

要在表创建后移除其 OID,请使用ALTER TABLE。

WITH OIDS
WITHOUT OIDS

这些是过时的语法,分别等价于WITH (OIDS)和WITH (OIDS=FALSE)。如果要同时指定OIDS设置和存储参数,必须使用WITH ( ... )语法;见上文。

ON COMMIT

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

PRESERVE ROWS

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

DELETE ROWS

临时表中的所有行都会在每个事务块结束时删除。实际上,每次提交时都会自动执行一次TRUNCATE。用于分区表时,这个操作不会级联到其分区。

DROP

在当前事务块结束时删除临时表。用于分区表时,此操作会删除其分区;用于带有继承子表的表时,则会删除其依赖子表。

TABLESPACE tablespace_name

tablespace_name是要创建新表的表空间名称。如果未指定,则查询default_tablespace;如果表是临时表,则查询temp_tablespaces。

USING INDEX TABLESPACE tablespace_name

该子句允许选择与 UNIQUE、PRIMARY KEY 或 EXCLUDE 约束相关联的索引要创建在哪个表空间中。若未指定,则参考default_tablespace;如果该表是临时表,则参考temp_tablespaces。

存储参数

WITH子句可以为表以及与UNIQUE、PRIMARY KEY或EXCLUDE约束关联的索引指定存储参数。索引的存储参数记载于CREATE INDEX。当前可用于表的存储参数列在下面。对于其中许多参数,如下所示,还存在一个同名但带有toast.前缀的附加参数,用于控制表的二级TOAST表(如果有)的行为(有关 TOAST 的更多信息请参见第 67.2 节)。如果设置了表参数值而未设置等效的toast.参数,则 TOAST 表会使用表参数的值。不支持为分区表指定这些参数,但可以为单独的叶分区指定。

fillfactor (integer)

表的填充因子是 10 到 100 之间的百分比。100(完全填充)是默认值。指定较小的填充因子时,INSERT操作只将表页填充到指定百分比;每页的剩余空间保留用于更新该页上的行。这样,UPDATE就有机会将行的更新副本放在与原行相同的页面上,这比放在不同页面上更高效。对于从不更新其条目的表,完全填充是最佳选择;但对于频繁更新的表,适合使用较小的填充因子。不能为 TOAST 表设置此参数。

parallel_workers (integer)

这设置用于协助并行扫描该表的工作进程数量。如果未设置,系统将根据关系大小确定一个值。规划器选择的实际工作进程数量可能更少,例如由于max_worker_processes的设置。

autovacuum_enabled, toast.autovacuum_enabled (boolean)

为特定表启用或禁用自动清理守护进程。如果为真,自动清理守护进程将按照第 24.1.6 节中讨论的规则,在该表上执行自动 VACUUM 和/或 ANALYZE 操作。如果为假,则该表不会被自动清理,但为了防止事务 ID 回卷,仍可能对其执行自动清理。有关回卷防护的更多信息,见第 24.1.5 节。注意,如果autovacuum参数为假,则自动清理守护进程根本不会运行(防止事务 ID 回卷的情况除外);为单独表设置存储参数也不会覆盖这一点。因此,显式将此存储参数设为 true 往往意义不大,设为 false 才更有用。

autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (integer)

autovacuum_vacuum_threshold参数的每表取值。

autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (floating point)

autovacuum_vacuum_scale_factor参数的每表取值。

autovacuum_analyze_threshold (integer)

autovacuum_analyze_threshold参数的每表取值。

autovacuum_analyze_scale_factor (floating point)

autovacuum_analyze_scale_factor参数的每表取值。

autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (integer)

autovacuum_vacuum_cost_delay参数的每表取值。

autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (integer)

autovacuum_vacuum_cost_limit参数的每表取值。

autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (integer)

vacuum_freeze_min_age参数的每表取值。注意,自动清理会忽略大于系统范围autovacuum_freeze_max_age设置一半的每表 autovacuum_freeze_min_age 参数。

autovacuum_freeze_max_age, toast.autovacuum_freeze_max_age (integer)

autovacuum_freeze_max_age参数的每表取值。注意,自动清理会忽略大于系统范围设置的每表 autovacuum_freeze_max_age 参数(它只能设置得更小)。

autovacuum_freeze_table_age, toast.autovacuum_freeze_table_age (integer)

vacuum_freeze_table_age参数的每表取值。

autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (integer)

vacuum_multixact_freeze_min_age参数的每表取值。注意,自动清理会忽略大于系统范围autovacuum_multixact_freeze_max_age设置一半的每表 autovacuum_multixact_freeze_min_age 参数。

autovacuum_multixact_freeze_max_age, toast.autovacuum_multixact_freeze_max_age (integer)

autovacuum_multixact_freeze_max_age参数的每表取值。注意,自动清理会忽略大于系统范围设置的每表 autovacuum_multixact_freeze_max_age 参数(它只能设置得更小)。

autovacuum_multixact_freeze_table_age, toast.autovacuum_multixact_freeze_table_age (integer)

vacuum_multixact_freeze_table_age参数的每表取值。

log_autovacuum_min_duration, toast.log_autovacuum_min_duration (integer)

log_autovacuum_min_duration参数的每表取值。

user_catalog_table (boolean)

将该表声明为逻辑复制用途的附加目录表。详见第 48.6.2 节。不能为 TOAST 表设置此参数。

注解

不建议在新应用中使用 OID:在可能的情况下,优先使用标识列或其他序列生成器作为表的主键。不过,如果应用确实使用 OID 来标识表中的特定行,建议在该表的oid列上创建唯一约束,以确保即使计数器回卷,表中的 OID 也确实能唯一标识行。不要假定 OID 在不同表之间唯一;如果需要数据库范围的唯一标识符,请组合使用tableoid和行 OID。

提示

对于没有主键的表,不建议使用OIDS=FALSE,因为既没有 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 GENERATED BY DEFAULT AS IDENTITY,
     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)
);

创建同样的表,并为该表及其唯一索引都指定 70% 的填充因子:

CREATE TABLE distributors (
    did     integer,
    name    varchar(40),
    UNIQUE(name) WITH (fillfactor=70)
)
WITH (fillfactor=70);

创建表circles,并添加一个排他约束以防任意两个圆重叠:

CREATE TABLE circles (
    c circle,
    EXCLUDE USING gist (c WITH &&)
);

在表空间diskvol1中创建表cinemas:

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

创建一个复合类型和一个类型化表:

CREATE TYPE employee_type AS (name text, salary numeric);

CREATE TABLE employees OF employee_type (
    PRIMARY KEY (name),
    salary WITH OPTIONS DEFAULT 1000
);

创建一个范围分区表:

CREATE TABLE measurement (
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

创建一个在分区键中包含多个列的范围分区表:

CREATE TABLE measurement_year_month (
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate));

创建列表分区表:

CREATE TABLE cities (
    city_id      bigserial not null,
    name         text not null,
    population   bigint
) PARTITION BY LIST (left(lower(name), 1));

创建范围分区表的分区:

CREATE TABLE measurement_y2016m07
    PARTITION OF measurement (
    unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');

使用分区键中的多个列创建范围分区表的几个分区:

CREATE TABLE measurement_ym_older
    PARTITION OF measurement_year_month
    FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);

CREATE TABLE measurement_ym_y2016m11
    PARTITION OF measurement_year_month
    FOR VALUES FROM (2016, 11) TO (2016, 12);

CREATE TABLE measurement_ym_y2016m12
    PARTITION OF measurement_year_month
    FOR VALUES FROM (2016, 12) TO (2017, 01);

CREATE TABLE measurement_ym_y2017m01
    PARTITION OF measurement_year_month
    FOR VALUES FROM (2017, 01) TO (2017, 02);

创建列表分区表的分区:

CREATE TABLE cities_ab
    PARTITION OF cities (
    CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b');

创建一个本身还要进一步分区的列表分区表分区,然后再向其添加一个分区:

CREATE TABLE cities_ab
    PARTITION OF cities (
    CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population);

CREATE TABLE cities_ab_10000_to_100000
    PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);

兼容性

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

临时表

尽管 CREATE TEMPORARY TABLE 的语法看起来类似于 SQL 标准,但其效果并不相同。按标准,临时表只需定义一次,并会自动存在于每个需要它的会话中(内容初始为空)。而 PostgreSQL 要求每个会话都为每个要使用的临时表发出自己的 CREATE TEMPORARY TABLE 命令。这使不同会话可以出于不同目的使用相同的临时表名;而标准做法则要求给定临时表名的所有实例都必须具有相同的表结构。

标准对临时表行为的定义在实践中被广泛忽略。PostgreSQL 在这一点上的行为与多种其他 SQL 数据库相似。

SQL 标准还区分全局和局部临时表,其中局部临时表在每个会话内的每个 SQL 模块中都有独立的内容集合,但其定义仍在多个会话之间共享。由于 PostgreSQL 不支持 SQL 模块,这一区别在 PostgreSQL 中没有意义。

出于兼容性考虑,PostgreSQL 接受在临时表声明中使用 GLOBAL 和 LOCAL 关键字,但它们目前没有效果。不鼓励使用这些关键字,因为未来版本的 PostgreSQL 可能会采用更符合标准的解释。

临时表的 ON COMMIT 子句也与 SQL 标准相似,但存在一些差异。如果省略 ON COMMIT 子句,SQL 规定默认行为是 ON COMMIT DELETE ROWS。然而,PostgreSQL 中的默认行为是 ON COMMIT PRESERVE ROWS。SQL 中不存在 ON COMMIT DROP 选项。

非延迟唯一性约束

当 UNIQUE 或 PRIMARY KEY 约束不可延迟时,只要有行被插入或修改,PostgreSQL 就会立刻检查唯一性。SQL 标准规定应只在语句结束时强制唯一性;例如,当单个命令会更新多个键值时,这两者就会产生差异。若要获得符合标准的行为,应将约束声明为 DEFERRABLE 但不延迟(即 INITIALLY IMMEDIATE)。注意,这可能明显慢于立即检查唯一性。

列检查约束

SQL 标准规定,CHECK 列约束只能引用其所作用的列;只有 CHECK 表约束才能引用多列。PostgreSQL 并不强制这一限制;它对列检查约束和表检查约束一视同仁。

EXCLUDE 约束

EXCLUDE 约束类型是 PostgreSQL 的扩展。

NULL “约束”

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

继承

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

零列的表

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

多个标识列

PostgreSQL 允许一个表拥有多个标识列。该标准指定一个表最多只能有一个标识列。放宽这一限制主要是为了给模式更改或迁移提供更大的灵活性。请注意,INSERT 命令仅支持一个适用于整个语句的覆盖子句,因此对行为不同的多个标识列支持并不好。

LIKE 子句

虽然 SQL 标准中存在 LIKE 子句,但 PostgreSQL 接受的许多 LIKE 选项并不在标准中,而标准中的某些选项又没有被 PostgreSQL 实现。

WITH 子句

WITH 子句是 PostgreSQL 的扩展;存储参数和 OID 都不属于标准内容。

表空间

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

类型化表

类型化表实现了 SQL 标准的一个子集。按照标准,类型化表除了具有与底层复合类型相对应的列之外,还应有一个额外的“自引用列”。PostgreSQL 不显式支持自引用列,但使用 OID 功能可以达到相同的效果。

PARTITION BY 子句

PARTITION BY 子句是 PostgreSQL 的扩展。

PARTITION OF 子句

PARTITION OF 子句是 PostgreSQL 的扩展。

提交更正

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