Skip to content

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 ) } [ opclass ] [ 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)。默认搜索路径首先包括临时模式,因此在临时表存在时,不会为新计划选择同名现有永久表,除非使用模式限定名称引用它们。在临时表上创建的任何索引也会自动成为临时索引。

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

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

UNLOGGED #

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

如果指定此项,则与未记录表一起创建的任何序列(用于标识或序列列)也将创建为未记录序列。

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

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

COMPRESSION compression_method #

COMPRESSION 子句设置列的压缩方法。仅支持可变宽度数据类型压缩,且仅在列的存储模式为 mainextended 时使用。(有关列存储模式的信息,请参阅 ALTER TABLE。)为分区表设置此属性没有直接影响,因为此类表没有自己的存储,但新创建的分区将继承配置的值。支持的压缩方法为 pglzlz4。(仅当在构建 PostgreSQL 时使用 --with-lz4 时才可用 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(有关详细信息,请参见第 38.16.3 节)。

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

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

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

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.24.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 不同,它们不是可以存储的实际值,而是表示该值不受限制。可以将 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 设置的更多信息,请参见第 73.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.4.1 节)。可以引用系统列 tableoid,但不能引用任何其他系统列。

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

当一张表有多个 CHECK 约束时,它们将按名称按字母顺序对每一行进行测试,在检查 NOT NULL 约束之后。(9.5 之前的 PostgreSQL 版本不会遵循 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

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

UNIQUE 约束指定表的一组或多列只能包含唯一值。唯一表约束的行为与唯一列约束的行为相同,但具有跨多个列的附加功能。因此,该约束强制要求任意两行至少在其中一列中不同。

对于唯一约束,除非指定了 NULLS NOT DISTINCT,否则不认为空值相等。

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

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

添加唯一约束将自动在约束中使用的列或列组上创建一个唯一 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(请参见 第 64 章);目前这意味着 无法使用。尽管允许使用,但将 B 树或哈希索引与排除约束一起使用几乎没有意义,因为这并不会比普通的唯一约束做得更好。因此,在实践中,访问方法将始终是

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 不允许多列外键的一列为空,除非所有外键列都为空;如果它们都为空,则不需要在引用表中匹配该行。MATCH SIMPLE 允许任何外键列为空;如果它们中的任何一个为空,则不需要在引用表中匹配该行。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 类型的访问方法。有关更多信息,请参阅 第 63 章。如果未指定此选项,则为新表选择默认表访问方法。有关更多信息,请参阅 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 的更多信息,请参见第 73.2 节)。如果设置了表参数值,但未设置等效的toast.参数,则 TOAST 表将使用表的参数值。不支持为分区表指定这些参数,但您可以为各个叶分区指定它们。

fillfactor (integer) #

表的填充因子是 10 到 100 之间的百分比。100(完全填充)是默认值。当指定较小的填充因子时,INSERT 操作仅将表页填充到指定的百分比;每页上的剩余空间保留用于更新该页上的行。这给了 UPDATE 机会将行的更新副本放在与原始副本相同的页面上,这比将其放在不同的页面上更高效,并且更有可能进行 仅堆元组更新。对于永远不更新其条目的表,完全填充是最佳选择,但在大量更新的表中,较小的填充因子是合适的。此参数不能为 TOAST 表设置。

toast_tuple_target (integer) #

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

parallel_workers (integer) #

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

autovacuum_enabled, toast.autovacuum_enabled (boolean) #

启用或禁用特定表的自动清理守护程序。如果为真,自动清理守护程序将根据 第 25.1.6 节 中讨论的规则对该表执行自动 VACUUM 和/或 ANALYZE 操作。如果为假,此表将不会自动清理,除非要防止事务 ID 环绕。有关环绕预防的更多信息,请参阅 第 25.1.5 节。请注意,如果 autovacuum 参数为假,则自动清理守护程序根本不会运行(除非要防止事务 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。如果 trueVACUUM 和自动真空将执行截断,并且截断页面的磁盘空间将返回给操作系统。请注意,截断需要表上的 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_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) #

将表声明为逻辑复制的附加目录表。有关详细信息,请参见 第 49.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);

创建范围分区表的 partition

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

在分区键中创建具有多列的范围分区表的几个 partition

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

创建列表分区表的 partition

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

创建列表分区表的 partition(该 partition 本身被进一步分区),然后向其中添加一个 partition

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

创建哈希分区表的 partition

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

创建默认 partition

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根本不记录NOT NULL约束的名称,因此它们不受唯一性限制。这可能会在未来版本中更改。

继承

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

零列表

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

多个标识列

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

生成列

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

LIKE子句

虽然LIKE子句存在于 SQL 标准中,但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