# 创建表

CREATE TABLE — 定义一个新表

# 概要

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ 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 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 ( 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 } ]

# 描述

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

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

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

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

定义约束有两种方式:表约束和列约束。列约束被定义为列定义的一部分。表约束定义不绑定到特定列,它可以包含多个列。每个列约束也可以写成表约束;当约束只影响一列时,列约束只是一种方便使用的符号。

为了能够创建一个表,你必须有用法对所有列类型或在条款,分别。

# 参数

暂时的或者温度

如果指定,则将该表创建为临时表。临时表在会话结束时自动删除,或者在当前事务结束时自动删除(请参阅提交时以下)。默认搜索_路径首先包括临时模式,因此当临时表存在时,不会为新计划选择同名的现有永久表,除非它们被模式限定名称引用。在临时表上创建的任何索引也自动是临时的。

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

可选地,全球的要么当地的可以写在前面暂时的要么温度.这目前在 PostgreSQL 中没有任何区别,并且已被弃用;看兼容性以下。

未记录

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

如果不存在

如果已存在同名关系,则不要抛出错误。在这种情况下发出通知。请注意,不能保证现有关系与已创建的关系相同。

表名

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

的 *类型名称*

创建一个类型表,它的结构来自指定的复合类型(名称可选模式限定)。类型表与它的类型相关联;例如,如果类型被删除,表将被删除(使用DROP TYPE ...级联)。

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

列名

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

数据类型

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

整理 *整理*

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

压缩 *压缩方法*

压缩子句设置列的压缩方法。仅可变宽度数据类型支持压缩,并且仅在列的存储模式为主要的要么扩展的.(看更改表有关列存储模式的信息。)为分区表设置此属性没有直接影响,因为此类表没有自己的存储,但配置的值将被新创建的分区继承。支持的压缩方法是pglzlz4.(lz4仅在以下情况下可用--with-lz4在构建 PostgreSQL 时使用。)此外,*压缩方法*可默认明确指定默认行为,即咨询默认_吐司_压缩数据插入时的设置,以确定要使用的方法。

继承 ( *父表* [, ... ] )

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

用于继承在新的子表和它的父表之间创建一个持久的关系。对父级的模式修改通常也会传播给子级,默认情况下,子表的数据包含在父级的扫描中。

如果在多个父表中存在相同的列名,除非每个父表中列的数据类型匹配,否则会报错。如果没有冲突,则合并重复的列以形成新表中的单个列。如果新表的列名列表包含同样被继承的列名,则数据类型必须同样与继承的列匹配,并且列定义合并为一个。如果新表明确指定列的默认值,则此默认值会覆盖继承的列声明中的任何默认值。否则,任何为该列指定默认值的父级都必须指定相同的默认值,否则会报错。

查看约束以与列基本相同的方式合并:如果多个父表和/或新表定义包含同名查看约束条件,这些约束条件都必须有相同的校验表达式,否则会报错。具有相同名称和表达式的约束将合并为一份。标记的约束没有继承权在任何情况下,父母都不会被考虑。请注意,一个未命名的检查新表中的约束永远不会被合并,因为将始终为其选择唯一的名称。

存储设置也会从父表复制。

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

按{RANGE | LIST | HASH}({*列名* | ( *表示* ) } [ *opclass* ] [, ...] )

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

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

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

分区表不支持排除制约因素;但是,您可以在单个分区上定义这些约束。

看见第5.11节更多关于表分区的讨论。

分割*父表*{对于值*分区_绑定_规范*|默认值}

将表创建为隔断指定父表的。该表既可以创建为特定值的分区,也可以使用价值观或者使用违约。父表中存在的任何索引、约束和用户定义的行级触发器都将克隆到新分区上。

这个*分区_绑定_规范*必须对应于父表的分区方法和分区键,并且不能与该父表的任何现有分区重叠。带有在里面用于列表分区,形式为从…起用于范围分区,并且具有用于哈希分区。

*分区绑定表达式*是任何无变量表达式(不允许使用子查询、窗口函数、聚合函数和集合返回函数)。其数据类型必须与相应分区键列的数据类型匹配。表达式在表创建时计算一次,因此它甚至可以包含易失性表达式,例如当前时间戳.

创建列表分区时,无效的可以指定为表示分区允许分区键列为空。但是,对于给定的父表,这样的列表分区不能超过一个。无效的无法为范围分区指定。

创建范围分区时,使用从…起是一个包含的界限,而上限用是一种排他性的束缚。即,在从…起列表是该分区对应的分区键列的有效值,而名单上没有。请注意,必须根据行比较规则来理解此语句(第9.24.5节).例如按范围划分(x,y),一个分区边界从(1,2)到(3,4)允许x=1任何y> =2, x=2任何非空yx=3任何y<4.

特殊价值观MINVALUE最大值可以在创建范围分区时使用,以指示列的值没有下限或上限。例如,使用从(最小值)到(10)允许任何小于10的值,以及使用从(10)到(最大值)允许任何大于或等于10的值。

当创建一个包含多个列的范围分区时,使用最大值作为下限的一部分,以及MINVALUE作为上限的一部分。例如,使用从(0,最大值)到(10,最大值)允许第一个分区键列大于0且小于或等于10的任何行。类似地,使用从('a',最小值)到('b',最小值)允许第一个分区键列以“a”开头的任何行。

注意,如果MINVALUE最大值用于分区绑定的一列,则后续所有列必须使用相同的值。例如(10,最小值,0)不是有效的界限;你应该写(10,MINVALUE,MINVALUE).

还要注意一些元素类型,例如时间戳,有一个“无限”的概念,这只是另一个可以存储的值。这与MINVALUE最大值,它们不是可以存储的真实值,而是表示该值是无限的。最大值可以被认为是大于任何其他值,包括“无限”和MINVALUE小于任何其他值,包括“负无穷大”。因此,范围从(‘无穷大’)到(最大值)不是一个空范围;它只允许存储一个值——“无限”。

如果违约指定后,将创建该表作为父表的默认分区。此选项不适用于哈希分区表。不适合给定父分区的任何其他分区的分区密钥值将被路由到默认分区。

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

创建哈希分区时,必须指定模数和余数。模量必须是正整数,余数必须是小于模量的非负整数。通常,在初始设置哈希分区表时,您应该选择一个等于分区数的模数,并将每个表分配相同的模量和不同的余数(请参阅下面的示例)。但是,不需要每个分区都具有相同的模量,只要求哈希分区表的分区中发生的每个模量都是下一个较大模量的一个因子。这允许增量增加分区的数量,而不需要同时移动所有数据。例如,假设您有一个包含8个分区的散列分区表,每个分区都有模数8,但是发现有必要将分区数增加到16.可以分离模-8分区中的一个,创建两个新的模数-16分区,覆盖密钥空间的同一部分(一个具有等于分离分区的其余部分的余数,另一个为等于该值加8的余数),并用数据重新填充它们。然后,您可以对每个模数8分区重复此操作,可能在稍后的时间重复,直到没有保留。虽然这可能在每个步骤中仍然涉及大量的数据移动,但它仍然比创建一个全新的表并同时移动所有数据要好。

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

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

诸如截断之类的操作通常会影响表及其所有继承子级,这些操作将级联到所有分区,但也可以在单个分区上执行。注意,删除分区时升降台需要接受访问独占锁定父表。

就像*源表* [ *喜欢你的选择吗* ... ]

这个喜欢子句指定一个表,新表从中自动复制所有列名、它们的数据类型以及它们的NOTNULL约束。

不像继承,新表和原始表在创建完成后完全解耦。对原始表的更改将不会应用于新表,并且不可能在原始表的扫描中包含新表的数据。

也不像继承,复制的列和约束喜欢不会与类似命名的列和约束合并。如果明确或在另一个文件中指定了相同的名称喜欢子句,发出错误信号。

可选的*喜欢你的选择吗*子句指定要复制的原始表的其他属性。指定包括…在内复制属性,并指定排除省略属性。排除这是默认值。如果为同一类对象制定了多个规范,则使用最后一个规范。可用选项包括:

包括评论

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

包括压缩

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

包括约束条件

检查约束将被复制。列约束和表约束之间没有区别。Not null约束总是复制到新表中。

包括违约

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

包括生成的

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

包括身份

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

包括索引

索引,主键, 唯一的排除原始表上的约束将在新表上创建。新索引和约束的名称是根据默认规则选择的,无论原始索引和约束是如何命名的。(此行为避免了新索引可能出现的重复名称失败。)

包括统计数据

扩展的统计信息被复制到新表中。

包括存储

存储复制的列定义的设置将被复制。默认行为是排除存储设置,从而使新表中复制的列具有特定于类型的默认设置。更多关于存储设置,请参见第70.2节.

包括所有

包括所有是一个缩写形式,选择所有可用的单个选项。(写一篇单独的文章可能会有用。)排除后面的条款包括所有选择除某些特定选项外的所有选项。)

这个喜欢子句还可以用于从视图、外部表或复合类型复制列定义。不适用的选项(例如:。,包括索引从一个角度来看)被忽略。

约束*你的名字*

列或表约束的可选名称。如果违反了约束,则约束名称会出现在错误消息中,因此col必须是正面的可用于向客户端应用程序传递有用的约束信息。(需要双引号来指定包含空格的约束名称。)如果未指定约束名称,系统将生成一个名称。

非空

该列不允许包含空值。

无效的

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

本条款仅用于与非标准SQL数据库兼容。在新的应用中不鼓励使用它。

支票(*表示*)[无继承权]

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

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

带有标记的约束没有继承权不会传播到子表。

当一个表有多个检查约束,在检查后,将按名称的字母顺序对每一行进行测试非空限制。(9.5之前的PostgreSQL版本不遵守任何特定的解雇令。)检查限制条件。)

违约*默认表达式*

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

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

始终生成为(*第二代expr*)存储

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

关键词存储表示该列将在写入时计算并存储在磁盘上。

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

生成{ALWAYS | DEFAULT}作为标识[(*顺序选项* ) ]

此子句将列创建为标识栏。它将附加一个隐式序列,新行中的列将自动具有分配给它的序列中的值。这样一个专栏是含蓄的非空.

条款总是默认情况下确定在中如何显式处理用户指定的值插入使现代化命令。

在一个插入命令,如果总是选择时,仅当插入语句指定覆盖系统值如果默认情况下则用户指定的值优先。看见插入详细信息。(在复制命令时,无论此设置如何,始终使用用户指定的值。)

在一个使现代化命令,如果总是如果选中,则将列更新为除违约将被拒绝。如果默认情况下选择后,该列可以正常更新。(没有最重要的合同条款使现代化命令。)

可选的*顺序选项*子句可用于覆盖序列的选项。看见创建序列详细信息。

唯一的(列约束)
独特的(*列名* [, ... ] ) [ 包括(*列名* [, ...])](表约束)

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

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

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

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

添加唯一约束将自动在约束中使用的列或列组上创建唯一的btree索引。

可选的包括子句将一个或多个列添加到该索引中,这些列只是“有效负载”:不会对它们强制执行唯一性,并且不能基于这些列搜索索引。但是,它们可以通过仅索引扫描进行检索。请注意,虽然约束不会对包含的列强制执行,但它仍然取决于这些列。因此,对此类列的某些操作(例如。,下降柱)可能导致级联约束和索引删除。

主键(列约束)
主键(*列名* [, ... ] ) [ 包括(*列名* [, ...])](表约束)

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

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

主键强制执行与以下组合相同的数据约束:唯一的非空但是,将一组列标识为主键也可以提供有关架构设计的元数据,因为主键意味着其他表可以依赖这组列作为行的唯一标识符。

当放在一张有隔板的桌子上,主键约束与前面描述的约束相同唯一的限制。

添加主键约束将在约束中使用的列或列组上自动创建唯一的btree索引。

可选的包括子句将一个或多个列添加到该索引中,这些列只是“有效负载”:不会对它们强制执行唯一性,并且不能基于这些列搜索索引。但是,它们可以通过仅索引扫描进行检索。请注意,虽然约束不会对包含的列强制执行,但它仍然取决于这些列。因此,对此类列的某些操作(例如。,下降柱)可能导致级联约束和索引删除。

排除[使用]*指数法* ] ( *排除_元素*与*操作人员* [, ... ] ) *索引参数*[WHERE(*谓语* ) ]

这个排除子句定义了一个排除约束,该约束保证,如果使用指定的运算符对指定列或表达式上的任意两行进行比较,则不会返回所有这些比较符合事实的.如果所有指定的运算符都测试相等性,则这相当于唯一的约束,尽管普通的唯一约束会更快。但是,排除约束可以指定比简单等式更一般的约束。例如,可以指定一个约束,使表中没有两行包含重叠的圆(请参见)第8.8节)通过使用&&操作人员

排除约束是使用索引实现的,因此每个指定的运算符必须与适当的运算符类相关联(请参见第11.10节)对于索引访问方法*指数法.运算符必须是可交换的。每个排除_元素*可以选择指定运算符类和/或排序选项;这些都在下面进行了详细描述创建索引.

访问方法必须支持amgettuple(见第62章); 目前这意味着不能使用杜松子酒。虽然这是允许的,但使用B-树或哈希索引加上排除约束几乎没有意义,因为这并没有比普通的唯一约束做得更好的地方。所以在实践中,访问方法总是GiST或SP GiST。

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

推荐人*参考表* [ ( *参考柱*)]匹配*火柴类型*[删除时]*参照动作*[更新]*参照动作* ](列约束)
外键(*列名* [, ... ] ) 推荐人*参考表* [ ( *参考柱* [, ... ] ) ] [匹配]*火柴类型*[删除时]*参照动作*[更新]*参照动作* ](表约束)

这些子句指定了一个外键约束,它要求新表的一个或多个列组成的组只能包含与被引用表的某一行的被引用列中的值相匹配的值。如果*参考柱省略列表,即参考表*被使用了。被引用的列必须是被引用表中不可延迟的唯一或主键约束的列。用户必须具有推荐人对引用表(整个表或特定引用列)的权限。添加外键约束需要共享行独占锁定引用的表。请注意,不能在临时表和永久表之间定义外键约束。

插入到引用列中的值将使用给定的匹配类型与引用表和引用列的值进行匹配。有三种匹配类型:完全匹配, 匹配部分简单匹配(这是默认设置)。完全匹配不允许多列外键的一列为空,除非所有外键列都为空;如果它们都为null,则该行不需要在引用的表中有匹配项。简单匹配允许任何外键列为空;如果其中任何一个为空,则该行不需要在引用的表中具有匹配项。匹配部分尚未实施。(当然,非空可以对引用列应用约束,以防止出现这些情况。)

此外,当引用列中的数据发生更改时,会对该表列中的数据执行某些操作。这个删除时子句指定删除被引用表中的被引用行时要执行的操作。同样地更新子句指定在将引用表中的引用列更新为新值时要执行的操作。如果行已更新,但引用的列并未实际更改,则不会执行任何操作。除不采取行动即使约束声明为可延迟,检查也不能延迟。每个条款都有以下可能的措施:

不采取行动

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

限制

生成一个错误,指示删除或更新将导致外键约束冲突。这和不采取行动只是支票不能延期。

大量

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

设为空

将引用列设置为空。

设置默认值

将引用列设置为其默认值。(如果默认值不为空,则引用表中必须有一行与默认值匹配,否则操作将失败。)

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

可推迟
不可推迟

这将控制是否可以延迟约束。不可延迟的约束将在每个命令后立即检查。可推迟的约束检查可以推迟到事务结束(使用设置约束条件命令)。不可推迟这是默认值。目前只有唯一的, 主键, 排除推荐人(外键)约束接受此条款。非空检查约束是不能推迟的。请注意,延迟约束不能用作冲突仲裁员插入包含关于冲突,请更新条款

最初是立即的
最初推迟

如果约束是可延迟的,则此子句指定检查约束的默认时间。如果约束是最初是立即的,则会在每个语句后进行检查。这是默认设置。如果约束是最初推迟,仅在交易结束时进行检查。约束检查时间可以通过设置约束条件命令

使用*方法*

此可选子句指定用于存储新表内容的表访问方法;该方法需要是类型为的访问方法桌子看见第61章了解更多信息。如果未指定此选项,将为新表选择默认的表访问方法。看见违约_桌子_通道_方法了解更多信息。

与(*存储参数* [= *价值*] [, ... ] )

本条款规定了表或索引的可选存储参数;看见存储参数下面是更多信息。为了向后兼容具有表的子句还可以包括OID=错误要指定新表的行不应包含OID(对象标识符),OID=真不再受支持。

没有耳垢

这是用于声明表的向后兼容语法没有耳垢,创建一个表和艾滋不再受支持。

承诺

事务块末尾的临时表的行为可以使用承诺.三个选项是:

保留行

交易结束时不采取特殊行动。这是默认行为。

删除行

临时表中的所有行将在每个事务块结束时删除。本质上,一个自动的截断在每次提交时完成。在分区表上使用时,它不会级联到分区。

临时表将被丢弃在当前事务块的末尾。在分区表上使用时,此操作会删除其分区,在具有继承子级的表上使用时,会删除从属子级。

表空间*表空间名称*

这*表空间名称*是要在其中创建新表的表空间的名称。如果没有指定,默认_表空间被咨询,或温度_表空间如果表是临时的。对于分区表,由于表本身不需要存储,因此指定的表空间会覆盖默认表空间当没有明确指定其他表空间时,作为用于任何新创建的分区的默认表空间。

使用索引表空间 *表空间名称*

此子句允许选择与索引关联的表空间独特,首要的关键, 要么排除将创建约束。如果没有指定,默认_表空间被咨询,或温度_表空间如果表是临时的。

# 存储参数

子句可以指定存储参数对于表和与 a 关联的索引独特,首要的关键, 或者排除约束。索引的存储参数记录在创建索引.下面列出了当前可用于表的存储参数。对于其中许多参数,如图所示,还有一个同名的附加参数,前缀为吐司。,它控制表的辅助 TOAST 表(如果有)的行为(请参阅第 70.2 节有关 TOAST 的更多信息)。如果设置了表参数值并且等效吐司。参数不是,TOAST 表将使用表的参数值。不支持为分区表指定这些参数,但您可以为单个叶分区指定它们。

填充因子(整数)

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

toast_tuple_target(整数)

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

并行工作者(整数)

这设置了应用于协助并行扫描此表的工作人员数量。如果未设置,系统将根据关系大小确定一个值。计划器或使用并行扫描的实用程序语句选择的实际工作人员数量可能会更少,例如由于设置最大限度_工人_流程.

autovacuum_enabled,toast.autovacuum_enabled(布尔值)

启用或禁用特定表的 autovacuum 守护程序。如果为 true,autovacuum 守护进程将自动执行真空和/或分析该表上的操作遵循讨论的规则第 25.1.6 节.如果为 false,则不会自动清空此表,除非防止事务 ID 回绕。看第 25.1.5 节了解更多关于环绕预防的信息。请注意,如果自动真空参数为假;设置单个表的存储参数不会覆盖它。因此,很少将这个存储参数显式设置为真的, 只为错误的.

真空索引清理,toast.vacuum_index_cleanup(枚举)

强制或禁用索引清理真空在这张桌子上运行。默认值为汽车.和离开,索引清理被禁用,与它已启用,并且汽车每次都动态做出决定真空运行。动态行为允许真空避免不必要地扫描索引以删除很少的死元组。强制禁用所有索引清理可以加快速度真空非常重要,但如果表修改频繁,也可能导致索引严重膨胀。这INDEX_CLEANUP参数真空,如果指定,覆盖此选项的值。

真空截断,toast.vacuum_truncate(布尔值)

启用或禁用真空以尝试截断此表末尾的任何空页。默认值为真的.如果真的,真空和 autovacuum 进行截断并将截断页面的磁盘空间返回给操作系统。请注意,截断需要访问独家锁在桌子上。这截短参数真空,如果指定,覆盖此选项的值。

autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (整数)

每个表的值自动真空_真空_临界点范围。

autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (浮点)

每个表的值自动真空_真空_规模_因素范围。

autovacuum_vacuum_insert_threshold, toast.autovacuum_vacuum_insert_threshold(整数)

每个表的值自动真空_真空_插入_临界点范围。-1 的特殊值可用于禁用表上的插入真空。

autovacuum_vacuum_insert_scale_factor,toast.autovacuum_vacuum_insert_scale_factor(浮点)

每个表的值自动真空_真空_插入_规模_因素范围。

autovacuum_analyze_threshold (整数)

每个表的值自动真空_分析_临界点范围。

autovacuum_analyze_scale_factor (浮点)

每个表的值自动真空_分析_规模_因素范围。

autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (浮点)

每个表的值自动真空_真空_成本_延迟范围。

autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (整数)

每个表的值自动真空_真空_成本_限制范围。

autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (整数)

每个表的值真空_冻结_分钟_年龄范围。请注意,autovacuum 将忽略每个表autovacuum_freeze_min_age大于系统范围一半的参数自动真空_冻结_最大限度_年龄环境。

autovacuum_freeze_max_age,toast.autovacuum_freeze_max_age(整数)

每个表的值自动真空_冻结_最大限度_年龄范围。请注意,autovacuum 将忽略每个表autovacuum_freeze_max_age大于系统范围设置的参数(只能设置得更小)。

autovacuum_freeze_table_age,toast.autovacuum_freeze_table_age(整数)

每个表的值真空_冻结_桌子_年龄范围。

autovacuum_multixact_freeze_min_age,toast.autovacuum_multixact_freeze_min_age(整数)

每个表的值真空_多方位_冻结_分钟_年龄范围。请注意,autovacuum 将忽略每个表autovacuum_multixact_freeze_min_age大于系统范围一半的参数自动真空_多方位_冻结_最大限度_年龄环境。

autovacuum_multixact_freeze_max_age,toast.autovacuum_multixact_freeze_max_age(整数)

每个表的值自动真空_多方位_冻结_最大限度_年龄范围。请注意,autovacuum 将忽略每个表autovacuum_multixact_freeze_max_age大于系统范围设置的参数(只能设置得更小)。

autovacuum_multixact_freeze_table_age,toast.autovacuum_multixact_freeze_table_age(整数)

每个表的值真空_多方位_冻结_桌子_年龄范围。

log_autovacuum_min_duration,toast.log_autovacuum_min_duration(整数)

每个表的值日志_自动真空_分钟_期间范围。

用户目录表(布尔值)

出于逻辑复制的目的将该表声明为附加目录表。看第 49.6.2 节详情。不能为 TOAST 表设置此参数。

# 笔记

PostgreSQL 自动为每个唯一约束和主键约束创建索引以强制唯一性。因此,没有必要为主键列显式创建索引。(看创建索引了解更多信息。)

当前实现中不继承唯一约束和主键。这使得继承和唯一约束的组合相当不正常。

一个表不能超过 1600 列。(实际上,由于元组长度的限制,有效限制通常较低。)

# 例子

创建表电影和表经销商

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

为表定义唯一的表约束电影.可以在表的一列或多列上定义唯一表约束:

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

为表定义主键表约束电影

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

为表定义主键约束经销商.下面两个例子是等价的,第一个使用表约束语法,第二个使用列约束语法:

CREATE TABLE distributors (
    did     integer,
    name    varchar(40),
    PRIMARY KEY(did)
);

CREATE TABLE distributors (
    did     integer PRIMARY KEY,
    name    varchar(40)
);

为列分配文字常量默认值姓名, 安排列的默认值做过通过选择序列对象的下一个值来生成,并将默认值设为修改时间是插入行的时间:

CREATE TABLE distributors (
    name      varchar(40) DEFAULT 'Luso Films',
    did       integer DEFAULT nextval('distributors_serial'),
    modtime   timestamp DEFAULT current_timestamp
);

定义两个非空表上的列约束经销商,其中一个被明确命名:

CREATE TABLE distributors (
    did     integer CONSTRAINT no_null NOT NULL,
    name    varchar(40) NOT NULL
);

姓名柱子:

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

创建表具有防止任何两个圆重叠的排除约束:

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

创建表电影院在表空间中磁盘卷1

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;

# 兼容性

创建表命令符合 SQL 标准,但下面列出了例外情况。

# 临时表

虽然语法创建临时表与SQL标准类似,效果不一样。在标准中,临时表只定义一次,并在每个需要它们的会话中自动存在(从空内容开始)。相反,PostgreSQL 要求每个会话发出自己的创建临时表每个要使用的临时表的命令。这允许不同的会话将相同的临时表名用于不同的目的,而标准的方法将给定临时表名的所有实例限制为具有相同的表结构。

该标准对临时表行为的定义被广泛忽略。PostgreSQL 在这一点上的行为类似于其他几个 SQL 数据库。

SQL 标准还区分了全局临时表和本地临时表,其中本地临时表为每个会话中的每个 SQL 模块都有一组单独的内容,尽管它的定义仍然在会话之间共享。由于 PostgreSQL 不支持 SQL 模块,因此这种区别在 PostgreSQL 中无关紧要。

出于兼容性考虑,PostgreSQL 将接受全球的当地的临时表声明中的关键字,但它们目前无效。不鼓励使用这些关键字,因为 PostgreSQL 的未来版本可能会对其含义采用更符合标准的解释。

提交时临时表子句也类似于 SQL 标准,但有一些区别。如果提交时子句被省略,SQL 指定默认行为是提交删除行.但是,PostgreSQL 中的默认行为是提交保留行.这提交删除SQL 中不存在该选项。

# 非延迟唯一性约束

当一个独特或者首要的关键约束是不可延迟的,只要插入或修改一行,PostgreSQL 就会立即检查唯一性。SQL 标准说,唯一性应该只在语句的末尾强制执行。例如,当单个命令更新多个键值时,这会有所不同。要获得符合标准的行为,请将约束声明为可延期的但不延期(即,最初立即)。请注意,这可能比立即唯一性检查要慢得多。

# 列检查约束

SQL标准说查看列约束只能引用它们适用的列;只要查看表约束可以引用多个列。PostgreSQL 不强制执行此限制;它对待列和表检查约束是一样的。

# 排除约束

排除约束类型是 PostgreSQL 扩展。

# 空值“约束”

空值“约束”(实际上是非约束)是对 SQL 标准的 PostgreSQL 扩展,包含在内是为了与其他一些数据库系统兼容(并与非空约束)。由于它是任何列的默认值,因此它的存在只是噪音。

# 约束命名

SQL 标准规定,表和域约束必须具有在包含表或域的模式中唯一的名称。PostgreSQL 比较宽松:它只要求约束名称在附加到特定表或域的约束中是唯一的。但是,对于基于索引的约束(独特,首要的关键, 和排除约束),因为关联索引的名称与约束相同,并且索引名称在同一模式内的所有关系中必须是唯一的。

目前,PostgreSQL 不记录名称非空完全没有约束,因此它们不受唯一性限制。这可能会在未来的版本中改变。

# 遗产

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

# 零列表

PostgreSQL 允许创建一个没有列的表(例如,创建表 foo();)。这是 SQL 标准的扩展,它不允许零列表。零列表本身并不是很有用,但不允许使用它们会产生奇怪的特殊情况更改表删除列,因此忽略此规范限制似乎更清晰。

# 多个身份列

PostgreSQL 允许一张表有多个标识列。该标准规定一张表最多可以有一个标识列。这主要是为了给模式更改或迁移提供更大的灵活性。请注意,插入command 仅支持一个覆盖整个语句的覆盖子句,因此不能很好地支持具有不同行为的多个标识列。

# 生成的列

选项已储存不是标准的,但也被其他 SQL 实现使用。SQL 标准没有指定生成列的存储。

# 喜欢条款

虽然一个子句存在于 SQL 标准中,PostgreSQL 为其接受的许多选项都没有在标准中,并且标准的一些选项没有被 PostgreSQL 实现。

# 条款

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

# 表空间

表空间的 PostgreSQL 概念不是标准的一部分。因此,条款表空间使用索引表空间是扩展。

# 类型表

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

# 分区方式条款

分区方式子句是 PostgreSQL 扩展。

# 分区条款

分区子句是 PostgreSQL 扩展。

# 也可以看看

更改表, 删除表, 创建表为, 创建表空间, 创建类型