2024年9月26日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不受支持的版本: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

CREATE TABLE

CREATE TABLE — 定义新表

概要

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | 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 | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | 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 | DEFAULT }
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

where column_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
  NULL |
  CHECK ( expression ) [ NO INHERIT ] |
  DEFAULT default_expr |
  GENERATED ALWAYS AS ( generation_expr ) STORED |
  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters |
  PRIMARY KEY index_parameters |
  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
    [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

and table_constraint is:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] ( 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 referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

and like_option is:

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

and partition_bound_spec is:

IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
  TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )

index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:

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

exclude_element in an EXCLUDE constraint is:

{ column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

referential_action in a FOREIGN KEY/REFERENCES constraint is:

{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }

描述

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

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

CREATE TABLE 还会自动创建一个数据类型,该数据类型表示对应于表中一行的复合类型。因此,表不能与同一模式中任何现有的数据类型具有相同的名称。

可选的约束子句指定约束(测试),新的或更新的行必须满足这些约束才能使插入或更新操作成功。约束是一个 SQL 对象,它以各种方式帮助定义表中有效值的集合。

有两种方法可以定义约束:表约束和列约束。列约束定义为列定义的一部分。表约束定义不与特定列绑定,并且可以包含多个列。每个列约束也可以写成表约束;列约束仅是一种用于约束仅影响一列时的符号约定。

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

参数

TEMPORARYTEMP #

如果指定,则表将作为临时表创建。临时表在会话结束时自动删除,或者可以选择在当前事务结束时删除(请参见下面的ON COMMIT)。默认的 search_path 首先包含临时模式,因此在临时表存在时,不会为新计划选择名称相同的现有永久表,除非它们使用模式限定名称进行引用。在临时表上创建的任何索引也自动成为临时索引。

自动清理守护进程 无法访问,因此无法清理或分析临时表。因此,应通过会话 SQL 命令执行适当的清理和分析操作。例如,如果要在复杂查询中使用临时表,则明智的做法是在填充临时表后对其运行 ANALYZE

可以选择在TEMPORARYTEMP 之前编写GLOBALLOCAL。这目前在PostgreSQL 中没有任何区别,并且已弃用;请参见下面的兼容性

UNLOGGED #

如果指定,则表将作为非日志表创建。写入非日志表的数据不会写入预写日志(请参见第 28 章),这使得它们比普通表快得多。但是,它们不是崩溃安全的:非日志表在崩溃或非正常关闭后会自动截断。非日志表的内容也不会复制到备用服务器。在非日志表上创建的任何索引也自动成为非日志索引。

如果指定了此选项,则与非日志表一起创建的任何序列(用于标识或序列列)也将作为非日志序列创建。

IF NOT EXISTS #

如果已存在具有相同名称的关系,则不要抛出错误。在这种情况下会发出通知。请注意,不能保证现有关系与本来要创建的关系有任何相似之处。

table_name #

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

OF type_name #

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

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

column_name #

要在新表中创建的列的名称。

data_type #

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

COLLATE collation #

COLLATE 子句为列分配排序规则(该列必须是可排序规则的数据类型)。如果未指定,则使用列数据类型的默认排序规则。

STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } #

此表单设置列的存储模式。这控制此列是在内联还是在辅助TOAST表中保存,以及数据是否应压缩。 PLAIN 必须用于固定长度的值,例如 integer,并且是内联的、未压缩的。 MAIN 用于内联的可压缩数据。 EXTERNAL 用于外部的、未压缩的数据,而EXTENDED 用于外部的、压缩的数据。编写DEFAULT 将存储模式设置为列数据类型的默认模式。对于大多数支持非PLAIN 存储的数据类型,EXTENDED 是默认值。使用EXTERNAL 将使对非常大的textbytea 值的子字符串操作运行速度更快,但代价是增加了存储空间。有关更多信息,请参见第 65.2 节

COMPRESSION compression_method #

COMPRESSION 子句设置列的压缩方法。压缩仅受可变宽度数据类型支持,并且仅在列的存储模式为mainextended 时使用。(有关列存储模式的信息,请参见ALTER TABLE。)为分区表设置此属性不会产生直接影响,因为此类表没有自己的存储,但配置的值将被新创建的分区继承。支持的压缩方法是pglzlz4。(lz4 仅在构建PostgreSQL 时使用了--with-lz4 时才可用。)此外,compression_method 可以是default 以显式指定默认行为,即在数据插入时查询default_toast_compression 设置以确定要使用的方法。

INHERITS ( parent_table [, ... ] ) #

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

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

如果相同的列名存在于多个父表中,则会报告错误,除非列的数据类型在每个父表中都匹配。如果没有冲突,则合并重复列以在新表中形成单个列。如果新表的列名列表包含也继承的列名,则数据类型也必须与继承的列(s) 匹配,并且列定义将合并为一个。如果新表为列显式指定了默认值,则此默认值将覆盖从继承的列声明中获取的任何默认值。否则,为列指定默认值的任何父表都必须指定相同的默认值,否则将报告错误。

CHECK 约束的合并方式与列基本相同:如果多个父表和/或新的表定义包含同名的 CHECK 约束,则这些约束必须具有相同的检查表达式,否则将报告错误。具有相同名称和表达式的约束将合并为一个副本。父表中标记为 NO INHERIT 的约束将不会被考虑。请注意,新表中未命名的 CHECK 约束永远不会被合并,因为始终会为其选择一个唯一的名称。

STORAGE 设置也会从父表复制。

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

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

可选的 PARTITION BY 子句指定了对表进行分区的策略。这样创建的表称为 分区表。括号内的列或表达式列表构成表的 分区键。在使用范围或哈希分区时,分区键可以包含多个列或表达式(最多 32 个,但此限制可以在构建 PostgreSQL 时更改),但对于列表分区,分区键必须由单个列或表达式组成。

范围和列表分区需要一个 btree 运算符类,而哈希分区需要一个哈希运算符类。如果未显式指定运算符类,则将使用相应类型的默认运算符类;如果不存在默认运算符类,则将引发错误。当使用哈希分区时,使用的运算符类必须实现支持函数 2(有关详细信息,请参见 第 36.16.3 节)。

分区表被划分为子表(称为分区),这些子表是使用单独的 CREATE TABLE 命令创建的。分区表本身是空的。插入表中的数据行将根据分区键中列或表达式的值路由到一个分区。如果不存在与新行中的值匹配的分区,则会报告错误。

分区表不支持 EXCLUDE 约束;但是,您可以在各个分区上定义这些约束。

有关表分区的更多讨论,请参见 第 5.12 节

PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT } #

将表创建为指定父表的 分区。可以使用 FOR VALUES 将表创建为特定值的指定分区,也可以使用 DEFAULT 将表创建为默认分区。父表中存在的任何索引、约束和用户定义的行级触发器都将在新分区上克隆。

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

partition_bound_expr 是任何无变量表达式(不允许使用子查询、窗口函数、聚合函数和返回集合的函数)。其数据类型必须与相应分区键列的数据类型匹配。表达式在表创建时只会被评估一次,因此它甚至可以包含易变表达式,例如 CURRENT_TIMESTAMP

在创建列表分区时,可以指定 NULL 来表示分区允许分区键列为 null。但是,对于给定的父表,此类列表分区不能超过一个。对于范围分区,不能指定 NULL

在创建范围分区时,使用 FROM 指定的下限是包含边界,而使用 TO 指定的上限是排除边界。也就是说,FROM 列表中指定的值是此分区相应分区键列的有效值,而 TO 列表中的值则不是。请注意,必须根据行比较规则理解此语句(第 9.25.5 节)。例如,给定 PARTITION BY RANGE (x,y),分区边界 FROM (1, 2) TO (3, 4) 允许 x=1 以及任何 y>=2x=2 以及任何非 null y,以及 x=3 以及任何 y<4

在创建范围分区时,可以使用特殊值 MINVALUEMAXVALUE 来指示列的值没有下限或上限。例如,使用 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”开头的任何行。

请注意,如果为分区边界的某一列使用了 MINVALUEMAXVALUE,则必须对所有后续列使用相同的值。例如,(10, MINVALUE, 0) 不是有效的边界;您应该写 (10, MINVALUE, MINVALUE)

另请注意,某些元素类型(例如 timestamp)具有“无限大”的概念,这只是可以存储的另一个值。这与 MINVALUEMAXVALUE 不同,MINVALUEMAXVALUE 不是可以存储的真实值,而是表示值不受限制的方式。MAXVALUE 可以被认为大于任何其他值,包括“无限大”,而 MINVALUE 可以被认为小于任何其他值,包括“负无限大”。因此,范围 FROM ('infinity') TO (MAXVALUE) 不是空范围;它允许精确存储一个值——“无限大”。

如果指定了 DEFAULT,则该表将被创建为父表的默认分区。此选项不适用于哈希分区表。不适合给定父表的任何其他分区的分区键值将被路由到默认分区。

当表具有现有的 DEFAULT 分区并向其添加新分区时,必须扫描默认分区以验证它是否不包含任何正确属于新分区中的行。如果默认分区包含大量行,这可能会很慢。如果默认分区是外部表或具有证明它不能包含应放置在新分区中的行的约束,则将跳过扫描。

在创建哈希分区时,必须指定模数和余数。模数必须是正整数,余数必须是非负整数,且小于模数。通常,在最初设置哈希分区表时,应选择一个等于分区数的模数,并为每个表分配相同的模数和不同的余数(请参见下面的示例)。但是,不需要每个分区都具有相同的模数,只需要哈希分区表的分区中出现的每个模数都是下一个较大模数的因数即可。这允许在不一次移动所有数据的情况下逐步增加分区数。例如,假设您有一个具有 8 个分区的哈希分区表,每个分区的模数为 8,但发现需要将分区数增加到 16。您可以分离一个模数为 8 的分区,创建两个新的模数为 16 的分区,覆盖键空间的相同部分(一个余数等于分离的分区的余数,另一个余数等于该值加上 8),并使用数据重新填充它们。然后,您可以对每个模数为 8 的分区重复此操作——也许在稍后的时间——直到没有剩余的分区为止。虽然这在每个步骤中可能仍然涉及大量数据移动,但它仍然比创建整个新表并一次移动所有数据要好。

分区必须与所属的分区表的列名和类型相同。对分区表的列名或类型的修改将自动传播到所有分区。CHECK 约束将由每个分区自动继承,但单个分区可以指定其他 CHECK 约束;与父级中具有相同名称和条件的其他约束将与父级约束合并。可以为每个分区分别指定默认值。但请注意,当通过分区表插入元组时,不会应用分区的默认值。

插入分区表的行将自动路由到正确的分区。如果不存在合适的分区,将发生错误。

通常影响表及其所有继承子项的操作(如 TRUNCATE)将级联到所有分区,但也可以在单个分区上执行。

请注意,使用 PARTITION OF 创建分区需要在父分区表上获取 ACCESS EXCLUSIVE 锁。同样,使用 DROP TABLE 删除分区需要在父表上获取 ACCESS EXCLUSIVE 锁。可以使用 ALTER TABLE ATTACH/DETACH PARTITION 以较弱的锁执行这些操作,从而减少对分区表上并发操作的干扰。

LIKE source_table [ like_option ... ] #

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

INHERITS 不同,新表和原始表在创建完成后完全分离。对原始表的更改不会应用于新表,并且无法在新表的扫描中包含原始表的数据。

此外,与 INHERITS 不同,LIKE 复制的列和约束不会与同名的列和约束合并。如果在其他 LIKE 子句中显式或隐式指定了相同的名称,则会发出错误信号。

可选的 like_option 子句指定要复制原始表哪些附加属性。指定 INCLUDING 会复制属性,指定 EXCLUDING 会省略属性。 EXCLUDING 是默认值。如果对同一种对象进行了多次指定,则使用最后一次指定。可用的选项包括:

INCLUDING COMMENTS #

将复制复制列、约束和索引的注释。默认行为是排除注释,导致新表中复制的列和约束没有注释。

INCLUDING COMPRESSION #

将复制列的压缩方法。默认行为是排除压缩方法,导致列具有默认压缩方法。

INCLUDING CONSTRAINTS #

将复制 CHECK 约束。不区分列约束和表约束。非空约束始终复制到新表。

INCLUDING DEFAULTS #

将复制复制列定义的默认表达式。否则,不会复制默认表达式,导致新表中复制的列具有空默认值。请注意,复制调用数据库修改函数(例如 nextval)的默认值可能会在原始表和新表之间创建函数链接。

INCLUDING GENERATED #

将复制复制列定义的任何生成表达式。默认情况下,新列将是常规的基本列。

INCLUDING IDENTITY #

将复制复制列定义的任何标识规范。为新表的每个标识列创建一个新序列,与旧表关联的序列分开。

INCLUDING INDEXES #

将在新表上创建原始表上的索引、PRIMARY KEYUNIQUEEXCLUDE 约束。新索引和约束的名称根据默认规则选择,而不管原始名称如何。(此行为避免了新索引可能出现的重复名称错误。)

INCLUDING STATISTICS #

扩展统计信息将复制到新表。

INCLUDING STORAGE #

将复制复制列定义的 STORAGE 设置。默认行为是排除 STORAGE 设置,导致新表中复制的列具有特定于类型的默认设置。有关 STORAGE 设置的更多信息,请参见 第 65.2 节

INCLUDING ALL #

INCLUDING ALL 是一个简写形式,选择所有可用的单个选项。(在 INCLUDING ALL 之后编写单个 EXCLUDING 子句可能很有用,以选择除某些特定选项之外的所有选项。)

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

CONSTRAINT constraint_name #

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

NOT NULL #

该列不允许包含空值。

NULL #

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

此子句仅为了与非标准 SQL 数据库兼容而提供。在新的应用程序中不建议使用它。

CHECK ( expression ) [ NO INHERIT ] #

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

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

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

当表具有多个 CHECK 约束时,将在检查 NOT NULL 约束后,按名称的字母顺序逐行测试它们。(PostgreSQL 9.5 之前的版本没有遵守 CHECK 约束的任何特定触发顺序。)

DEFAULT default_expr #

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

任何未指定列值的插入操作都将使用默认表达式。如果列没有默认值,则默认为 null。

GENERATED ALWAYS AS ( generation_expr ) STORED #

此子句将该列创建为 生成列。无法写入该列,读取时将返回指定表达式的结果。

关键字 STORED 是必需的,表示该列将在写入时计算并存储在磁盘上。

生成表达式可以引用表中的其他列,但不能引用其他生成列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。

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

此子句将该列创建为 标识列。它将有一个隐式序列附加到它,在新插入的行中,该列将自动分配来自序列的值。这样的列隐式地为 NOT NULL

ALWAYSBY DEFAULT 子句确定如何在 INSERTUPDATE 命令中处理用户显式指定的值。

INSERT 命令中,如果选择了 ALWAYS,则只有当 INSERT 语句指定 OVERRIDING SYSTEM VALUE 时才会接受用户指定的值。如果选择了 BY DEFAULT,则用户指定的值优先。有关详细信息,请参见 INSERT。(在 COPY 命令中,始终使用用户指定的值,而不管此设置如何。)

UPDATE 命令中,如果选择了 ALWAYS,则将拒绝将该列更新为除 DEFAULT 以外的任何值的任何更新。如果选择了 BY DEFAULT,则可以正常更新该列。(UPDATE 命令没有 OVERRIDING 子句。)

可选的 sequence_options 子句可用于覆盖序列的参数。可用的选项包括 CREATE SEQUENCE 中显示的选项,以及 SEQUENCE NAME nameLOGGEDUNLOGGED,它们允许选择序列的名称和持久性级别。没有 SEQUENCE NAME,系统将为序列选择一个未使用的名称。没有 LOGGEDUNLOGGED,序列将与表具有相同的持久性级别。

UNIQUE [ NULLS [ NOT ] DISTINCT ] (列约束)
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束) #

UNIQUE 约束指定表的 1 个或多个列的组只能包含唯一值。唯一表约束的行为与唯一列约束相同,但还具有跨多个列的功能。因此,该约束强制执行任何两行在这些列中的至少一列必须不同。

出于唯一约束的目的,空值不被视为相等,除非指定了 NULLS NOT DISTINCT

每个唯一约束都应命名一组与为表定义的任何其他唯一或主键约束命名的列集不同的列。(否则,将丢弃冗余的唯一约束。)

在为多级分区层次结构建立唯一约束时,目标分区表的 partition key 中的所有列以及其所有后代分区表中的所有列都必须包含在约束定义中。

添加唯一约束将自动在约束中使用的列或列组上创建唯一 btree 索引。创建的索引与唯一约束具有相同的名称。

可选的 INCLUDE 子句向该索引添加一个或多个只是 有效负载 的列:不会对它们强制执行唯一性,并且无法根据这些列搜索索引。但是,可以通过仅索引扫描检索它们。请注意,尽管不会对包含的列强制执行约束,但它仍然依赖于它们。因此,对这些列的一些操作(例如,DROP COLUMN)可能会导致级联约束和索引删除。

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

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

主键约束应命名一组与为同一表定义的任何唯一约束命名的列集不同的列集。(否则,唯一约束是冗余的,将被丢弃。)

PRIMARY KEY 执行与 UNIQUENOT NULL 组合相同的约束。但是,将一组列标识为主键还提供了有关模式设计元数据,因为主键意味着其他表可以依赖这组列作为行的唯一标识符。

当放置在分区表上时,PRIMARY KEY 约束共享先前针对 UNIQUE 约束描述的限制。

添加 PRIMARY KEY 约束将自动在约束中使用的列或列组上创建一个唯一的 btree 索引。该索引与主键约束具有相同的名称。

可选的 INCLUDE 子句向该索引添加一个或多个只是 有效负载 的列:不会对它们强制执行唯一性,并且无法根据这些列搜索索引。但是,可以通过仅索引扫描检索它们。请注意,尽管不会对包含的列强制执行约束,但它仍然依赖于它们。因此,对这些列的一些操作(例如,DROP COLUMN)可能会导致级联约束和索引删除。

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

EXCLUDE 子句定义了一个排除约束,它保证如果使用指定的运算符对任何两行在指定的列或表达式上进行比较,则这些比较并非全部返回 TRUE。如果所有指定的运算符都测试相等性,则这等效于 UNIQUE 约束,尽管普通的唯一约束会更快。但是,排除约束可以指定比简单相等性更通用的约束。例如,您可以指定一个约束,即表中没有两行包含重叠的圆圈(请参阅 第 8.8 节),方法是使用 && 运算符。运算符必须是可交换的。

排除约束是使用与约束同名的索引实现的,因此每个指定的运算符都必须与索引访问方法 index_method 的相应运算符类相关联(请参阅 第 11.10 节)。每个 exclude_element 定义索引的一列,因此它可以选择指定排序规则、运算符类、运算符类参数和/或排序选项;这些在 CREATE INDEX 中进行了完整描述。

访问方法必须支持 amgettuple(请参阅 第 62 章);目前这意味着GIN不能使用。虽然允许使用,但使用 B 树或哈希索引与排除约束几乎没有意义,因为这不会做普通唯一约束做得更好的任何事情。因此,在实践中,访问方法将始终为GiSTSP-GiST.

predicate 允许您在表的子集上指定排除约束;在内部,这将创建一个部分索引。请注意,谓词周围需要括号。

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

这些子句指定外键约束,它要求新表的一列或多列组只能包含与引用表某一行的引用列值匹配的值。如果省略了 refcolumn 列表,则使用 reftable 的主键。否则,refcolumn 列表必须引用不可延迟的唯一或主键约束的列,或是非部分唯一索引的列。用户必须对引用表具有 REFERENCES 权限(整个表或特定的引用列)。添加外键约束需要在引用表上获得 SHARE ROW EXCLUSIVE 锁。请注意,外键约束不能在临时表和永久表之间定义。

插入到引用列中的值使用给定的匹配类型与引用表和引用列的值进行匹配。有三种匹配类型:MATCH FULLMATCH PARTIALMATCH SIMPLE(这是默认值)。MATCH FULL 不允许多列外键的一列为 null,除非所有外键列都为 null;如果它们都为 null,则不要求该行在引用表中具有匹配项。MATCH SIMPLE 允许任何外键列为 null;如果其中任何一个为 null,则不要求该行在引用表中具有匹配项。MATCH PARTIAL 尚未实现。(当然,可以对引用列应用 NOT NULL 约束以防止这些情况发生。)

此外,当引用列中的数据更改时,会在表列中的数据上执行某些操作。ON DELETE 子句指定在引用表中删除引用行时要执行的操作。同样,ON UPDATE 子句指定在引用表中的引用列更新为新值时要执行的操作。如果更新了行,但实际上没有更改引用列,则不会执行任何操作。除 NO ACTION 检查之外的其他引用操作都不能被延迟,即使约束被声明为可延迟的。每个子句都有以下可能的动作

NO ACTION #

生成一个错误,指示删除或更新将导致外键约束冲突。如果约束被延迟,则如果仍然存在任何引用行,则将在约束检查时生成此错误。这是默认操作。

RESTRICT #

生成一个错误,指示删除或更新将导致外键约束冲突。这与 NO ACTION 相同,除了检查不可延迟。

CASCADE #

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

SET NULL [ ( column_name [, ... ] ) ] #

将所有引用列或引用列的指定子集设置为 null。只能为 ON DELETE 操作指定列的子集。

SET DEFAULT [ ( column_name [, ... ] ) ] #

将所有引用列或引用列的指定子集设置为其默认值。只能为 ON DELETE 操作指定列的子集。(如果默认值不为 null,则引用表中必须有一行与默认值匹配,否则操作将失败。)

如果引用列经常更改,则最好为引用列添加索引,以便可以更有效地执行与外键约束关联的引用操作。

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 命令更改约束检查时间。

USING method #

此可选子句指定用于存储新表内容的表访问方法;该方法需要是类型为 TABLE 的访问方法。有关更多信息,请参阅 第 61 章。如果未指定此选项,则为新表选择默认的表访问方法。有关更多信息,请参阅 default_table_access_method

创建分区时,表访问方法是其分区表的访问方法(如果已设置)。

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

本条款指定表或索引的可选存储参数;有关更多信息,请参见下面的存储参数。为了向后兼容,表的WITH子句还可以包含OIDS=FALSE以指定新表的行不应包含OID(对象标识符),OIDS=TRUE不再支持。

WITHOUT OIDS #

这是声明表WITHOUT OIDS的向后兼容语法,不再支持创建表WITH OIDS

ON COMMIT #

可以使用ON COMMIT控制事务块结束时临时表的行为。三个选项是

PRESERVE ROWS #

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

DELETE ROWS #

在每个事务块结束时,临时表中的所有行都将被删除。本质上,在每次提交时都会自动执行TRUNCATE。当用于分区表时,不会级联到其分区。

DROP #

在当前事务块结束时,将删除临时表。当用于分区表时,此操作将删除其分区;当用于具有继承子表的表时,它将删除相关的子表。

TABLESPACE tablespace_name #

tablespace_name是将在其中创建新表的表空间的名称。如果未指定,则会查询default_tablespace,或者如果表是临时表,则查询temp_tablespaces。对于分区表,由于表本身不需要存储,因此指定的表空间会覆盖default_tablespace作为默认表空间,用于在没有显式指定其他表空间时创建的任何新分区。

USING INDEX TABLESPACE tablespace_name #

此子句允许选择将在其中创建与UNIQUEPRIMARY KEYEXCLUDE约束关联的索引的表空间。如果未指定,则会查询default_tablespace,或者如果表是临时表,则查询temp_tablespaces

存储参数

WITH子句可以为表指定存储参数,以及为与UNIQUEPRIMARY KEYEXCLUDE约束关联的索引指定存储参数。索引的存储参数在CREATE INDEX中进行了说明。当前可用于表的存储参数如下所示。对于许多这些参数,如所示,还有一个名称前缀为toast.的其他参数,它控制表的辅助TOAST表的行为(如果存在)(有关TOAST的更多信息,请参见第 65.2 节)。如果设置了表参数值并且未设置等效的toast.参数,则TOAST表将使用表参数值。不支持为分区表指定这些参数,但您可以为各个叶子分区指定这些参数。

fillfactor (integer) #

表的fillfactor是一个介于10%到100%之间的百分比。100(完全打包)是默认值。当指定较小的fillfactor时,INSERT操作仅将表页打包到指定的百分比;每个页面的剩余空间保留用于更新该页上的行。这使UPDATE有机会将更新的行副本放在与原始行相同的页面上,这比将其放在不同的页面上效率更高,并且使仅堆元组更新更有可能发生。对于从未更新其条目的表,完全打包是最佳选择,但在更新频繁的表中,较小的fillfactor更合适。此参数不能设置为TOAST表。

toast_tuple_target (integer) #

toast_tuple_target指定在尝试压缩和/或将长列值移动到TOAST表之前所需的最小元组长度,它也是在开始进行toasting后尝试将长度减少到的目标长度。这会影响标记为External(用于移动)、Main(用于压缩)或Extended(用于两者)的列,并且仅适用于新元组。对现有行没有影响。默认情况下,此参数设置为每个块至少允许4个元组,使用默认块大小将为2040字节。有效值介于128字节和(块大小 - 标头)之间,默认为8160字节。更改此值对于非常短或非常长的行可能没有用。请注意,默认设置通常接近最佳,并且在某些情况下设置此参数可能会产生负面影响。此参数不能设置为TOAST表。

parallel_workers (integer) #

这设置了应使用多少个工作进程来协助对该表的并行扫描。如果未设置,系统将根据关系大小确定一个值。计划程序或使用并行扫描的实用程序语句选择的实际工作进程数可能更少,例如由于max_worker_processes的设置。

autovacuum_enabled, toast.autovacuum_enabled (boolean) #

启用或禁用特定表的自动清理守护进程。如果为true,则自动清理守护进程将在遵循第 24.1.6 节中讨论的规则后,对该表执行自动VACUUM和/或ANALYZE操作。如果为false,则不会对该表进行自动清理,除非是为了防止事务ID回绕。有关回绕预防的更多信息,请参见第 24.1.5 节。请注意,如果autovacuum参数为false,则自动清理守护进程根本不会运行(除非是为了防止事务ID回绕);设置各个表的存储参数不会覆盖该参数。因此,很少有必要将此存储参数显式设置为true,而仅设置为false

vacuum_index_cleanup, toast.vacuum_index_cleanup (enum) #

在对该表运行VACUUM时强制或禁用索引清理。默认值为AUTO。使用OFF禁用索引清理,使用ON启用索引清理,使用AUTO每次运行VACUUM时动态做出决策。动态行为允许VACUUM避免不必要地扫描索引以删除很少的死元组。强制禁用所有索引清理可以显着加快VACUUM的速度,但如果表修改频繁,也可能导致索引严重膨胀。VACUUMINDEX_CLEANUP参数(如果指定)将覆盖此选项的值。

vacuum_truncate, toast.vacuum_truncate (boolean) #

启用或禁用vacuum以尝试截断该表末尾的任何空页。默认值为true。如果为true,则VACUUM和自动清理将执行截断,并且截断页面的磁盘空间将返回到操作系统。请注意,截断需要对表进行ACCESS EXCLUSIVE锁定。VACUUMTRUNCATE参数(如果指定)将覆盖此选项的值。

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_vacuum_insert_threshold, toast.autovacuum_vacuum_insert_threshold (integer) #

autovacuum_vacuum_insert_threshold参数的每个表的值。特殊值-1可用于禁用表上的插入清理。

autovacuum_vacuum_insert_scale_factor, toast.autovacuum_vacuum_insert_scale_factor (floating point) #

autovacuum_vacuum_insert_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 (floating point) #

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_min_age 参数大于系统范围的 autovacuum_freeze_max_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_min_age 参数大于系统范围的 autovacuum_multixact_freeze_max_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) #

将表声明为逻辑复制的附加目录表。有关详细信息,请参见 第 47.6.2 节。此参数不能为 TOAST 表设置。

注释

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 orders (
    order_id     bigint not null,
    cust_id      bigint not null,
    status       text
) PARTITION BY HASH (order_id);

创建范围分区表的 partitions

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

在分区键中具有多列的范围分区表中创建一些 partitions

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);

创建列表分区表的 partitions

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

创建本身进一步分区的列表分区表的 partitions,然后向其中添加一个 partitions

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);

创建哈希分区表的 partitions

CREATE TABLE orders_p1 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);

创建默认 partitions

CREATE TABLE cities_partdef
    PARTITION OF cities DEFAULT;

兼容性

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 ROWSON COMMIT DROP 选项在 SQL 中不存在。

非延迟唯一性约束

UNIQUEPRIMARY KEY 约束不可延迟时,PostgreSQL 会在每次插入或修改行时立即检查唯一性。SQL 标准规定仅在语句结束时才应执行唯一性检查;例如,当单个命令更新多个键值时,这会产生差异。要获得符合标准的行为,请将约束声明为 DEFERRABLE 但不延迟(即 INITIALLY IMMEDIATE)。请注意,这可能比立即唯一性检查慢得多。

列检查约束

SQL 标准规定 CHECK 列约束只能引用它们适用的列;只有 CHECK 表约束才能引用多个列。PostgreSQL 不强制执行此限制;它将列和表检查约束视为相同。

EXCLUDE 约束

EXCLUDE 约束类型是 PostgreSQL 扩展。

外键约束

在外键操作 SET DEFAULTSET NULL 中指定列列表的能力是 PostgreSQL 的扩展。

外键约束可以引用唯一索引的列而不是主键或唯一约束的列,这是一种 PostgreSQL 扩展。

NULL 约束

NULL 约束(实际上是非约束)是 PostgreSQL 对 SQL 标准的扩展,它包含在内是为了与某些其他数据库系统兼容(以及与 NOT NULL 约束对称)。由于它是任何列的默认值,因此它的存在只是噪声。

约束命名

SQL 标准规定表和域约束必须具有在包含表或域的模式中唯一的名称。PostgreSQL 比较宽松:它仅要求约束名称在附加到特定表或域的约束中唯一。但是,基于索引的约束(UNIQUEPRIMARY KEYEXCLUDE 约束)不存在这种额外的自由,因为关联的索引与约束同名,并且索引名称必须在同一模式中的所有关系中唯一。

目前,PostgreSQL 根本不记录非空约束的名称,因此它们不受唯一性限制的影响。这可能会在将来的版本中发生变化。

继承

通过 INHERITS 子句实现的多重继承是 PostgreSQL 的语言扩展。SQL:1999 及更高版本使用不同的语法和语义定义单一继承。SQL:1999 样式的继承尚未得到 PostgreSQL 的支持。

零列表

PostgreSQL 允许创建没有列的表(例如,CREATE TABLE foo();)。这是对 SQL 标准的扩展,SQL 标准不允许零列表。零列表本身并没有什么用,但是不允许它们会为 ALTER TABLE DROP COLUMN 创建奇怪的特殊情况,因此忽略此规范限制似乎更简洁。

多个标识列

PostgreSQL 允许一个表拥有多个标识列。标准规定一个表最多只能有一个标识列。放松此限制主要是为了在执行模式更改或迁移时提供更大的灵活性。请注意,INSERT 命令只支持一个应用于整个语句的覆盖子句,因此拥有具有不同行为的多个标识列不受良好支持。

生成列

STORED 选项不是标准的,但也由其他 SQL 实现使用。SQL 标准未指定生成列的存储方式。

LIKE 子句

虽然 SQL 标准中存在 LIKE 子句,但 PostgreSQL 为其接受的许多选项都不在标准中,并且某些标准选项未由 PostgreSQL 实现。

WITH 子句

WITH 子句是 PostgreSQL 的扩展;存储参数不在标准中。

表空间

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

类型化表

类型化表实现了 SQL 标准的一个子集。根据标准,类型化表具有与底层复合类型相对应的列,以及另一列,该列是 自引用列PostgreSQL 不明确支持自引用列。

PARTITION BY 子句

PARTITION BY 子句是 PostgreSQL 的扩展。

PARTITION OF 子句

PARTITION OF 子句是 PostgreSQL 的扩展。

提交更正

如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表单 报告文档问题。