选择 打开 改范围 完整检索页

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

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 [, ... ] ) ]
[ 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 }
    [, ... ]
) ]
[ 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 |
  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 } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | ALL }

UNIQUEPRIMARY KEYEXCLUDE约束中的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 权限。

参数

TEMPORARYTEMP #

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

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

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

UNLOGGED #

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

IF NOT EXISTS

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

table_name

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

OF type_name

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

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

column_name

要在新表中创建的列名。

data_type

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

COLLATE collation

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

INHERITS ( parent_table [, ... ] )

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

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

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

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

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

LIKE source_table [ like_option ... ]

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

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

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

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

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

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

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

INCLUDING ALLINCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS的简写形式。

请注意,与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。

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

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

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

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

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

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

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

PRIMARY KEY 强制的数据约束与 UNIQUENOT 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(见 第 58 章);目前这意味着不能使用 GIN。 虽然允许,但在排他约束上使用 B-树或 hash 索引意义不大,因为它们做不到 比普通唯一约束更好的事情。因此,实践中访问方法总是 GiSTSP-GiST

predicate 允许你只在表的一个 子集上指定排他约束;在内部,这会创建一个部分索引。注意, 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的主键。被引用列必须是被引用表中不可延迟的唯一约束或主键约束的列。请注意,不能在临时表和永久表之间定义外键约束。

插入到引用列中的值会按照给定的匹配类型,与被引用表及其被引用列中的值进 行匹配。共有三种匹配类型:MATCH FULLMATCH PARTIALMATCH 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是默认值。目前,只有UNIQUEPRIMARY KEYEXCLUDEREFERENCES(外键)约束接受此子句。NOT NULLCHECK约束不可延迟。请注意,不能将可延迟约束用作包含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

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

存储参数

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

fillfactor (integer)

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

autovacuum_enabled, toast.autovacuum_enabled (boolean)

为特定表启用或禁用自动清理守护进程。如果为真,自动清理守护进程将按照 第 23.1.6 节 中讨论的规则,在该表上执行自动 VACUUM 和/或 ANALYZE 操作。如果为 假,则该表不会被自动清理,但为了防止事务 ID 回卷,仍可能对其执行自动清 理。有关回卷防护的更多信息,见 第 23.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)

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

注解

不建议在新应用中使用 OID:在可能的情况下,优先使用SERIAL或其他序列生成器作为表的主键。不过,如果应用确实使用 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 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)
);

创建同样的表,并为该表及其唯一索引都指定 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 命令符合 SQL 标准,但有下 列例外。

临时表

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

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

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

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

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

非延迟唯一性约束

UNIQUEPRIMARY 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 出现奇怪的特殊情况,因此忽略这 一规范限制看起来更整洁。

LIKE 子句

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

WITH 子句

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

表空间

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

类型化表

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

提交更正

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