Postgresql 中文操作指南

CREATE TABLE

CREATE TABLE — 定义一个新表

Synopsis

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 [, ... ] ) ] }

Description

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

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

CREATE TABLE 还自动创建一种数据类型,表示与表的一行相对应的复合类型。因此,表不能与同一架构中任何现有数据类型同名。

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

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

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

Parameters

  • TEMPORARY or TEMP #

    • 如果指定,表将创建为临时表。临时表将在会话结束时自动删除,或者可选地在当前事务结束时删除(请参见下文 ON COMMIT )。默认搜索路径首先包括临时架构,因此不会为新计划选择同名存在的永久表,除非它们用限定架构名称引用。在临时表上创建的任何索引也自动成为临时索引。

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

    • 可以选择在 TEMPORARYTEMP 之前编写 GLOBALLOCAL 。这本质上在 PostgreSQL 中没有区别,并且已被弃用;请参见 Compatibility

  • UNLOGGED #

    • 如果指定了,则该表将作为非日志记录表创建。写入非日志记录表的不会被写入预写式日志(参见 Chapter 30 ),这将使它们比常规表快得多。然而,它们并不安全:非日志记录表会在崩溃或不干净的关机后自动被截断。非日志记录表的内容也不会复制到备用服务器。在非日志记录表上创建的任何索引也都会自动记录为非日志记录。

    • 如果指定了这一点,那么与非日志记录表一起创建的任何序列(用于标识或序列号列)也会被创建为非日志记录。

  • IF NOT EXISTS #

    • 如果某个同名关系已经存在,则不要抛出错误。在这种情况下会发出通知。请注意,无法保证现有关系与将要创建的关系完全一样。

  • table_name #

    • 要创建的表名(可选地经过架构限定)。

  • OF _type_name_ #

    • 创建 typed table ,其结构来自指定的复合类型(可选地使用模式限定名)。类型化表与其类型绑定;例如,如果类型被删除(带 DROP TYPE …​ CASCADE ),则表也会被删除。

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

  • column_name #

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

  • data_type #

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

  • COLLATE _collation_ #

    • COLLATE 子句为该列分配特定规则(该列必须是可校对数据类型)。如果没有指定,则使用列数据类型默认的校对规则。

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

    • 此表单设置列的存储模式。此操作控制该列是内联保存还是在次要 TOAST 表中保存,以及数据是否应压缩。 PLAIN 必须用于定长值,例如 integer ,它内联且未压缩。 MAIN 用于内联可压缩数据。 EXTERNAL 用于外部未压缩数据, EXTENDED 用于外部压缩数据。编写 DEFAULT 会将存储模式设置为列数据类型的默认模式。对于支持非 PLAIN 存储的大多数数据类型, EXTENDED 是默认。使用 EXTERNAL 将使在非常大的 textbytea 值上执行子字符串运算的速度变快,但代价是增加存储空间。有关更多信息,请参阅 Section 73.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 子句指定了一个分区表的策略。因而创建的表称为 partitioned 表。括号内的列或表达式列表形成表的 partition key 。在使用范围或哈希分区时,分区键可包括多个列或表达式(最多 32 个,此限制在构建 PostgreSQL 时可更改),但在列表分区的情况下,分区键必须包含一个列或表达式。

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

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

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

    • 有关表分区的更多讨论,请参阅 Section 5.11

  • PARTITION OF _parent_table { FOR VALUES partition_bound_spec | DEFAULT }_ #

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

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

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

    • 在创建列表分区时,可指定 NULL 以表示该分区允许分区键列为空。但是,对于给定的父表,此类列表分区不能多于一个。无法为范围分区指定 NULL

    • 在创建范围分区时,使用 FROM 指定的下限是一个包容性上限,而使用 TO 指定的上限是一个非包容性上限。也就是说, FROM 列表中指定的值是此分区的分区键列的有效值,而 TO 列表中指定的值则是无效值。请注意,此语句必须根据逐行比较的规则( Section 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 是默认值。如果针对同一类型的对象进行了多个规范,则使用最后一个规范。可用的选项包括:

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

  • CONSTRAINT _constraint_name_ #

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

  • NOT NULL #

    • 不允许该列包含空值。

  • NULL #

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

    • 该子句仅用于与非标准SQL数据库的兼容性。在新的应用程序中不建议使用它。

  • CHECK ( _expression ) [ NO INHERIT ]_ #

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

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

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

    • 当一个表有多个 CHECK 约束时,在检查 NOT NULL 约束之后,将按名称按字母顺序对每行进行测试。(9.5之前的PostgreSQL版本并未遵守任何特定的 CHECK 约束激发顺序。)

  • DEFAULT _default_expr_ #

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

    • 对于任何未为该列指定值的插入操作,将使用默认表达式。如果某列没有默认值,那么该默认值为空。

  • GENERATED ALWAYS AS ( _generation_expr ) STORED_ #

    • 此子句将该列创建为 generated column 。该列无法写入,而在读取时将会返回指定表达式的结果。

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

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

  • GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( _sequence_options ) ]_ #

    • 此子句将该列创建为 identity column 。它将有一个隐式序列附加在它上面,并且新行中的列将自动获得该序列分配给它的值。此类列隐式 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 ] (column constraint) UNIQUE [ NULLS [ NOT ] DISTINCT ] ( _column_name [, …​ ] )_ [ INCLUDE ( _column_name [, …​])_ ] (table constraint) #

    • UNIQUE 约束指定一张表中的一组一个或多个列只能包含唯一值。唯一表约束的行为与唯一列约束的行为相同,另 -,它具有跨越多列的能力。因此,该约束强制任何两行至少在这些列中的一个列中不同。

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

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

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

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

    • 可选的 INCLUDE 子句会将一个或多个列添加 - 索引,这些列只是“负载”: 不会在它们上面强制实施唯一性,并且不能基于这些列搜索索引。但是可以通过仅索引扫描来检索它们。请注意,虽然对包含的列不强制实施该约束,但它仍然依赖于这些列。因此,对这些列进行的某些操作(例如 DROP COLUMN )会引起级联约束和索引删除。

  • PRIMARY KEY (column constraint) PRIMARY KEY ( _column_name [, …​ ] )_ [ INCLUDE ( _column_name [, …​])_ ] (table constraint) #

    • 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 约束,尽管普通的唯一约束会更快。但是,排除约束可以指定比简单的相等性更为通用的约束。例如,可以通过使用 && 运算符指定表中没有两行包含重叠圆的约束(请参阅 Section 8.8 )。运算符必须是可交换的。

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

    • 访问方法必须支持 amgettuple (请参阅 Chapter 64 );目前这意味着不能使用 GIN。虽然允许这样做,但将 B-tree 或哈希索引与排斥约束一起使用几乎没有意义,因为这样做没有任何事情是一个普通的唯一约束不能做得更好的。因此,在实践中,访问方法将始终是 GiST 或 SP-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 检查以外的参照操作不能被延迟,即使约束被声明为可延迟的。每个子句都有以下可能的动作:

    • 如果引用列经常改变,则明智的做法是向引用列添加一个索引,以便与外键约束相关联的参照操作可以更高效地执行。

  • 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 的访问方法。有关详细信息,请参阅 Chapter 63 。如果未指定此选项,则为新表选择默认表访问方法。有关详细信息,请参阅 default_table_access_method

  • WITH ( _storage_parameter [= value ] [, …​ ] )_ #

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

  • WITHOUT OIDS #

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

  • ON COMMIT #

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

  • TABLESPACE _tablespace_name_ #

    • tablespace_name 是要创建新表时使用的表空间的名称。如果未指定,将咨询 default_tablespace ,如果表为临时表,则咨询 temp_tablespaces 。对于分区表,由于表本身不需要存储,所以指定的表空间将覆盖 default_tablespace ,作为在未明确指定任何其他表空间时,用于任何新创建分区的默认表空间。

  • USING INDEX TABLESPACE _tablespace_name_ #

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

  • INCLUDING COMMENTS #

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

  • INCLUDING COMPRESSION #

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

  • INCLUDING CONSTRAINTS #

    • 将复制 CHECK 约束。不会区分列约束和表约束。not-null 约束始终复制到新表。

  • INCLUDING DEFAULTS #

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

  • INCLUDING GENERATED #

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

  • INCLUDING IDENTITY #

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

  • INCLUDING INDEXES #

    • 将复制原始表上的索引、 PRIMARY KEYUNIQUEEXCLUDE 约束到新表。新索引和约束的名称将根据默认规则选择,而不管原始名称如何。(此行为避免新索引发生可能的重名失败。)

  • INCLUDING STATISTICS #

    • 将扩展统计复制到新表。

  • INCLUDING STORAGE #

    • 将复制所复制的列定义的 STORAGE 设置。默认行为是排除 STORAGE 设置,导致新表中复制的列具有类型特定的默认设置。有关 STORAGE 设置的更多信息,请参阅 Section 73.2

  • INCLUDING ALL #

    • INCLUDING ALL 是选择所有可用单个选项的缩写形式。(可以有用的做法是在 INCLUDING ALL 之后编写单个 EXCLUDING 子句来选择所有选项,但特定的某些选项除外。)

  • NO ACTION #

    • 生成错误来指明删除或更新会导致外键约束违反。如果约束是延迟的,那么如果仍然存在任何引用行,则将在约束检查时间生成此错误。这是默认操作。

  • RESTRICT #

    • 生成错误来指明删除或更新会导致外键约束违反。这与 NO ACTION 相同,除了不能延迟检查。

  • CASCADE #

    • 删除引用所删除行的任何行,或将引用列的值更新为引用列的新值,分别对应于前面提到的行。

  • SET NULL [ ( _column_name [, …​ ] ) ]_ #

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

  • SET DEFAULT [ ( _column_name [, …​ ] ) ]_ #

    • 将所有引用列或指定部分引用列设置为它们的默认值。仅针对 ON DELETE 操作可指定部分列。(如果它们不为 null,则在引用表中必须存在与默认值匹配的行,否则操作将失败。)

  • PRESERVE ROWS #

    • 事务结束时不会执行任何特殊操作。这是默认行为。

  • DELETE ROWS #

    • 临时表中的所有行都将在每个事务块的结尾处被删除。基本上,每次提交都会执行一个自动的 TRUNCATE 。当在分区表上使用时,此操作不会级联到其分区。

  • DROP #

    • 临时表将在当前事务块的结尾处被取消。当在分区表上使用时,此操作将取消其分区,当在具有继承的子表上使用时,将取消依赖的子表。

Storage Parameters

WITH 子句可以对表指定 storage parameters ,以及与 UNIQUEPRIMARY KEYEXCLUDE 约束关联的索引。索引的存储参数已记录在 CREATE INDEX 中。目前可用于表的存储参数如下所列。对于其中许多参数,如所示,还有一个同名参数,前缀为 toast. ,它控制表的二级 TOAST 表的行为,如果有的话(有关 TOAST 的更多信息,请参见 Section 73.2 )。如果设置了表参数值,而未设置等效的 toast. 参数,则 TOAST 表将使用表的参数值。不支持为分区表指定这些参数,但你可以为各个叶子分区指定它们。

  • fillfactor (integer) #

    • 表的填充系数是介于 10 到 100 之间的百分比。100(完全填充)是默认值。指定较小的填充系数时, INSERT 操作只会将表页填充到所指示的百分比;每个页面上的剩余空间保留用于在该页面上更新行。这给了 UPDATE 一个将更新的行副本放在同一页面上(与原始行在同一页面上)的机会,这比将其放在不同的页面上更高效,并且使 heap-only tuple updates 更有可能发生。对于永远不会更新其条目的表,完全填充是最佳选择,但是在频繁更新的表中,较小的填充系数是合适的。此参数不能设置为 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) #

    • 启用或禁用某个特定表的自动真空守护进程。如果为真,则自动真空守护进程将按照 Section 25.1.6 中讨论的规则对该表执行自动 VACUUM 和/或 ANALYZE 操作。如果为假,则此表不会自动真空,除非要防止事务 ID 环绕。有关回绕预防的更多信息,请参见 Section 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) #

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

  • autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (integer) #

  • autovacuum_vacuum_scale_factortoast.autovacuum_vacuum_scale_factor ( floating point ) #

  • autovacuum_vacuum_insert_threshold, toast.autovacuum_vacuum_insert_threshold (integer) #

  • autovacuum_vacuum_insert_scale_factortoast.autovacuum_vacuum_insert_scale_factor ( floating point ) #

  • autovacuum_analyze_threshold (integer) #

  • autovacuum_analyze_scale_factor (floating point) #

  • autovacuum_vacuum_cost_delaytoast.autovacuum_vacuum_cost_delay ( floating point ) #

  • autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (integer) #

  • autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (integer) #

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

  • autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (integer) #

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

  • log_autovacuum_min_duration, toast.log_autovacuum_min_duration (integer) #

  • user_catalog_table (boolean) #

    • 将该表声明为用于逻辑复制的附加目录表。有关详情,请参见 Section 49.6.2 。无法针对 TOAST 表设置此参数。

Notes

PostgreSQL 会自动为每个唯一约束和主键约束创建索引以强制唯一性。因此,不必明确地为主键列创建索引。(有关更多信息,请参见 CREATE INDEX 。)

在当前实现中,不会继承唯一约束和主键。这会让继承与唯一约束的组合变得很混乱。

一个表最多有 1600 列。(在实践中,有效的限制通常较低,这是因为有元组长度约束)

Examples

创建表 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);

创建范围分区表的某个分区:

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;

Compatibility

CREATE TABLE 命令符合 SQL 标准,但例外情况如下所列。

Temporary Tables

尽管 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 中不存在。

Non-Deferred Uniqueness Constraints

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

Column Check Constraints

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

EXCLUDE Constraint

EXCLUDE 约束类型是 PostgreSQL 扩展。

Foreign Key Constraints

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

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

NULL “Constraint”

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

Constraint Naming

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

目前,PostgreSQL 根本不记录 NOT NULL 约束的名称,因此不受唯一性限制。这可能会在未来版本中更改。

Inheritance

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

Zero-Column Tables

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

Multiple Identity Columns

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

Generated Columns

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

LIKE Clause

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

WITH Clause

WITH 子句是 PostgreSQL 扩展;存储参数不符合标准。

Tablespaces

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

Typed Tables

类型表实现了一部分 SQL 标准。根据标准,类型化表有与底层复合类型对应的列以及另一个作为“自引用的列”的列。PostgreSQL 不显式支持自引用的列。

PARTITION BY Clause

PARTITION BY 子句是 PostgreSQL 扩展。

PARTITION OF Clause

PARTITION OF 子句是 PostgreSQL 扩展。