Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

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将存储模式设置为列数据类型的默认模式。EXTENDED是大多数支持非PLAIN存储的数据类型的默认值。使用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 创建了一个新的子表与其父表(或父表)之间的持久关系。父表(或父表)的模式修改通常也会传播到子表,并且默认情况下,子表的数据包含在父表(或父表)的扫描中。

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

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 和任何非空 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 的分区,直到不再有模数为 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子句为包含其列定义的列分配一个默认数据值。该值是任何无变量的表达式(特别是,不允许交叉引用当前表中的其他列)。子查询也不允许。默认表达式的类型必须与列的类型匹配。

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

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 ] (column constraint)
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (table constraint) #

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

启用或禁用真空以尝试截断此表末尾的任何空页。默认值为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 (浮点数) #

autovacuum_analyze_scale_factor 参数的每个表值。

autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (浮点数) #

autovacuum_vacuum_cost_delay 参数的每个表值。

autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (整数) #

autovacuum_vacuum_cost_limit 参数的每个表值。

autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (整数) #

vacuum_freeze_min_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围 autovacuum_freeze_max_age 设置一半的每个表 autovacuum_freeze_min_age 参数。

autovacuum_freeze_max_age, toast.autovacuum_freeze_max_age (整数) #

autovacuum_freeze_max_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围设置的每个表 autovacuum_freeze_max_age 参数(只能将其设置为更小)。

autovacuum_freeze_table_age, toast.autovacuum_freeze_table_age (整数) #

vacuum_freeze_table_age 参数的每个表值。

autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (整数) #

vacuum_multixact_freeze_min_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围 autovacuum_multixact_freeze_max_age 设置一半的每个表 autovacuum_multixact_freeze_min_age 参数。

autovacuum_multixact_freeze_max_age, toast.autovacuum_multixact_freeze_max_age (整数) #

autovacuum_multixact_freeze_max_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围设置的每个表 autovacuum_multixact_freeze_max_age 参数(只能将其设置为更小)。

autovacuum_multixact_freeze_table_age, toast.autovacuum_multixact_freeze_table_age (整数) #

vacuum_multixact_freeze_table_age 参数的每个表值。

log_autovacuum_min_duration, toast.log_autovacuum_min_duration (整数) #

log_autovacuum_min_duration 参数的每个表值。

user_catalog_table (布尔值) #

将表声明为逻辑复制的附加目录表。有关详细信息,请参阅第 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 定义唯一表约束。唯一表约束可以针对表的1列或多列定义

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

创建范围分区表的分区

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

创建默认分区

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

非延迟唯一性约束

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 的扩展。

另请参阅

ALTER TABLEDROP TABLECREATE TABLE ASCREATE TABLESPACECREATE TYPE