9.3 9.4 9.5 9.6 10 11 12 13 14 15 Current(16) 17
问题报告 纠错本页面

CREATE TABLE

CREATE TABLE — 定义一个新表

大纲

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] 表名 ( [
  { 列名 数据类型 [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION 压缩方法 ] [ COLLATE 排序规则 ] [ 列约束 [ ... ] ]
    | 表约束
    | LIKE 源表 [ LIKE选项 ... ] }
    [, ... ]
] )
[ INHERITS ( 父表 [, ... ] ) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { 列名 | ( 表达式 ) } [ COLLATE 排序规则 ] [ 操作类 ] [, ... ] ) ]
[ USING 方法 ]
[ WITH ( 存储参数 [= ] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE 表空间名 ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] 表名
    OF 类型名 [ (
  { 列名 [ WITH OPTIONS ] [ 列约束 [ ... ] ]
    | 表约束 }
    [, ... ]
) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { 列名 | ( 表达式 ) } [ COLLATE 排序规则 ] [ 操作类 ] [, ... ] ) ]
[ USING 方法 ]
[ WITH ( 存储参数 [= ] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE 表空间名 ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] 表名
    PARTITION OF 父表 [ (
  { 列名 [ WITH OPTIONS ] [ 列约束 [ ... ] ]
    | 表约束 }
    [, ... ]
) ] { FOR VALUES 分区边界规范 | DEFAULT }
[ PARTITION BY { RANGE | LIST | HASH } ( { 列名 | ( 表达式 ) } [ COLLATE 排序规则 ] [ 操作类 ] [, ... ] ) ]
[ USING 方法 ]
[ WITH ( 存储参数 [= ] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE 表空间名 ]

其中列约束为:

[ CONSTRAINT 约束名 ]
{ NOT NULL |
  NULL |
  CHECK ( 表达式 ) [ NO INHERIT ] |
  DEFAULT 默认表达式 |
  GENERATED ALWAYS AS ( 生成表达式 ) STORED |
  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( 序列选项 ) ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] 索引参数 |
  PRIMARY KEY 索引参数 |
  REFERENCES 引用表 [ ( 引用列 ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
    [ ON DELETE 引用操作 ] [ ON UPDATE 引用操作 ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

并且表约束为:

[ CONSTRAINT 约束名 ]
{ CHECK ( 表达式 ) [ NO INHERIT ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] ( 列名 [, ... ] ) 索引参数 |
  PRIMARY KEY ( 列名 [, ... ] ) 索引参数 |
  EXCLUDE [ USING 索引方法 ] ( 排除元素 WITH 操作符 [, ... ] ) 索引参数 [ WHERE ( 谓词 ) ] |
  FOREIGN KEY ( 列名 [, ... ] ) REFERENCES 引用表 [ ( 引用列 [, ... ] ) ]
    [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE 引用操作 ] [ ON UPDATE 引用操作 ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

并且LIKE选项为:

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

并且分区边界规范为:

IN ( 分区边界表达式 [, ...] ) |
FROM ( { 分区边界表达式 | MINVALUE | MAXVALUE } [, ...] )
  TO ( { 分区边界表达式 | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS 数字字面量, REMAINDER 数字字面量 )

索引参数UNIQUEPRIMARY KEYEXCLUDE约束中为:

[ INCLUDE ( 列名 [, ... ] ) ]
[ WITH ( 存储参数 [= ] [, ... ] ) ]
[ USING INDEX TABLESPACE 表空间名 ]

排除元素EXCLUDE约束中为:

{ 列名 | ( 表达式 ) } [ COLLATE 排序规则 ] [ 操作类 [ ( 操作类参数 =  [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

引用操作FOREIGN KEY/REFERENCES约束中为:

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

描述

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

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

CREATE TABLE也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中任何已有数据类型的名称。

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

有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列时方便书写的记号习惯。

要能创建一个表,你必须分别具有所有列类型或OF子句中类型的USAGE特权。

参数

TEMPORARY or TEMP #

如果指定,该表被创建为一个临时表。 临时表会被在会话结束时自动被删除,或者也可以选择在当前事务结束时删除(见下文的ON COMMIT)。 默认搜索路径首先包括临时模式,因此当临时表存在时,不会为新计划选择同名的已有的永久表,除非它们使用模式限定的名称进行引用。 在一个临时表上创建的任何索引也自动地变为临时的。

自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE

可以选择将GLOBALLOCAL写在TEMPORARYTEMP的前面。这当前在PostgreSQL中没有区别并且已被废弃,见Compatibility

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

此形式设置列的存储模式。这控制了该列是内联存储还是在一个次级 TOAST表中存储,以及数据是否需要压缩。 PLAIN必须用于固定长度的值,例如integer, 并且是内联的、未压缩的。MAIN用于内联的、可压缩的数据。 EXTERNAL用于外部的、未压缩的数据,而EXTENDED 用于外部的、压缩的数据。 写入DEFAULT会将存储模式设置为列数据类型的默认模式。 对于支持非PLAIN存储的大多数数据类型, EXTENDED是默认值。 使用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

创建范围分区时,由FROM指定的下限是一个包含范围, 而用TO指定的上限是排除范围。也就是说, 在FROM列表中指定的值是该分区的相应分区键列的有效值, 而TO列表中的值不是。请注意, 必须根据按行比较的规则来理解此语句(第 9.24.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不同, 它们不是可以存储的实际值,而是它们表示值无界的方式。MAXVALUE 可以被认为比任何其他值(包括“无穷”)都大的值,MINVALUE 可以被认为是比任何其他值(包括“负无穷”)都小的值。因此, 范围FROM ('infinity') TO (MAXVALUE)不是空的范围; 它只允许存储一个值— "infinity"。

如果指定了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 #

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

INCLUDING STATISTICS #

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

INCLUDING STORAGE #

STORAGE设置将会被复制到复制的列定义中。 默认行为是排除STORAGE设置,这会导致新表中的复制列 使用类型特定的默认设置。有关STORAGE设置的更多信息, 请参见第 73.2 节

INCLUDING ALL #

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

LIKE子句也能被用来从视图、外部表或组合类型拷贝列定义。不适合的选项(例如来自视图的INCLUDING INDEXES)会被忽略。

CONSTRAINT constraint_name #

一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似列必须为正的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如果没有指定约束名,系统将生成一个。

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子句为出现在其定义中的列赋予一个默认数据。该值是可以使用变量的表达式(特别是,不允许用对其他列的交叉引用)。子查询也是不允许的。 默认值表达式的数据类型必须匹配列的数据类型。

默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。

GENERATED ALWAYS AS ( generation_expr ) STORED #

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

关键字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约束指定一个表中的一列或多列组成的组包含唯一的值。 唯一表约束的行为与唯一列约束的行为相同,只是表约束能够跨越多列。 约束因此强制在这些列中的至少一列的任何两行必须不同。

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

每一个唯一表约束将命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不相同。 (否则,冗余的唯一约束将被丢弃。)

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

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

可选 INCLUDE子句向该索引添加一个或多个列是简单的payload:在它们上面唯一性是不强制的,并且该索引不能基于这些列搜索。 然而它们可以通过一个仅对索引的扫描检索。 请注意虽然约束在包含的列上是非强制的,但是它仍然依赖于它们。 因此,这样的列上的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。

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

PRIMARY KEY约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个主键,可以作为列约束或表约束。

主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余的并且会被丢弃)。

PRIMARY KEY强制的数据约束可以看成是UNIQUENOT NULL的组合, 然而,把一组列标识为主键也为模式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。

当放到分区表上时,PRIMARY KEY 约束共享前面描述的UNIQUE 约束的限制。

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

可选 INCLUDE子句向该索引添加一个或多个列是简单的payload:在它们上面唯一性是不强制的,并且该索引不能基于这些列搜索。 然而它们可以通过一个仅对索引的扫描检索。 请注意虽然约束在包含的列上是非强制的,但是它仍然依赖于它们。 因此,这样的列上的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。

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

EXCLUDE子句定义了一个排除约束,该约束保证如果 任意两行在指定的列或表达式上使用指定的操作符进行比较,不会有所有这些 比较返回TRUE。如果所有指定的操作符都测试相等,这等同于一个 UNIQUE约束,尽管普通的唯一约束会更快。然而,排除约束可以指定 比简单相等更一般的约束。例如,您可以指定一个约束,表中没有两行包含重叠的圆 (参见第 8.8 节),通过使用 &&操作符。操作符需要是可交换的。

排除约束使用索引实现,因此每个指定的操作符必须与适当的操作符类关联 (参见第 11.10 节),用于索引访问方法index_method。 每个exclude_element定义索引的一列,因此可以选择性地指定排序规则、 操作符类、操作符类参数和/或排序选项;这些在CREATE INDEX下有详细描述。

访问方法必须支持amgettuple(见第 64 章),目前这意味着GIN无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是GiSTSP-GiST

predicate允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周围的圆括号是必须的。

REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (column constraint)
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (table constraint) #

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

被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。 有三种匹配类型:MATCH FULLMATCH PARTIAL以及MATCH 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 KEYEXCLUDE以及REFERENCES(外键)约束接受这个子句。 NOT NULL以及CHECK约束是不可延迟的。 注意在包括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] [, ... ] ) #

这个子句为一个表或索引指定可选的存储参数,详见Storage Parameters 。 为了向后兼容性,表的WITH子句还可以包括OIDS=FALSE以便指定新表的行不应包含 OIDs (对象标识符),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 KEY或者EXCLUDE约束相关的索引将被创建在哪个表空间中。如果没有指定,将参考default_tablespace,或者如果表是临时的则参考temp_tablespaces

存储参数

WITH子句能够为表或与一个UNIQUEPRIMARY KEY或者EXCLUDE约束相关的索引指定存储参数。 用于索引的存储参数已经在CREATE INDEX中介绍过。 当前可用于表的存储参数在下文中列出。 如下文所示,对于很多这类参数,都有一个名字带有toast.前缀的附加参数,它能被用来控制该表的二级TOAST表(如果存在)的行为(关于 TOAST 详见第 73.2 节)。 如果一个表的参数值被设置但是相应的toast.参数没有被设置,那么 TOAST 表将使用该表的参数值。 不支持为分区表指定这些参数,但可以为单个叶子分区指定它们。

fillfactor (integer) #

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

toast_tuple_target (integer) #

在我们尝试压缩和/或将长列值移动到TOAST表中之前,toast_tuple_target指定需要的最小元组长度, 也是在toasting开始时尝试减少长度的目标长度。这会影响标记为 External(用于移动)、 Main(用于压缩)或 Extended(用于两者)的列,并且仅适用于新元组。 对现有行没有影响。 这仅影响标记为"外部"或"扩展"的列,并且仅适用于新元数 - 对现有行没有影响。 默认情况下此参数设置为允许每个块至少 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) #

启用或禁用vacuum以尝试截断此表末尾的任何空页。默认值为true。 如果trueVACUUM和autovacuum将执行截断,截断页的磁盘空间将返回到操作系统。 请注意,截断需要 ACCESS EXCLUSIVE在表上锁定。 VACUUMTRUNCATE参数,如果指定,覆盖此选项的值。

autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (integer) #

autovacuum_vacuum_threshold参数对于每个表的值。

autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (floating point) #

autovacuum_vacuum_scale_factor参数对于每个表的值。

autovacuum_vacuum_insert_threshold, toast.autovacuum_vacuum_insert_threshold (integer) #

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

autovacuum_vacuum_insert_scale_factor, toast.autovacuum_vacuum_insert_scale_factor (floating point) #

autovacuum_vacuum_insert_scale_factor参数对于每个表的值。

autovacuum_analyze_threshold (integer) #

autovacuum_analyze_threshold参数对于每个表的值。

autovacuum_analyze_scale_factor (floating point) #

autovacuum_analyze_scale_factor参数对于每个表的值。

autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (floating point) #

autovacuum_vacuum_cost_delay参数对于每个表的值。

autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (integer) #

autovacuum_vacuum_cost_limit参数对于每个表的值。

autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (integer) #

vacuum_freeze_min_age参数对于每个表的值。注意自动清理将忽略超过系统范围autovacuum_freeze_max_age参数一半的针对每个表的autovacuum_freeze_min_age参数。

autovacuum_freeze_max_age, toast.autovacuum_freeze_max_age (integer) #

autovacuum_freeze_max_age参数对于每个表的值。注意自动清理将忽略超过系统范围参数(只能被设置得较小)一半的针对每个表的autovacuum_freeze_max_age参数。

autovacuum_freeze_table_age, toast.autovacuum_freeze_table_age (integer) #

vacuum_freeze_table_age参数对于每个表的值。

autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (integer) #

vacuum_multixact_freeze_min_age参数对于每个表的值。注意自动清理将忽略超过系统范围autovacuum_multixact_freeze_max_age参数一半的针对每个表的autovacuum_multixact_freeze_min_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);

创建范围分区表的分区:

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标准,除了以下例外。

临时表

尽管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约束)在一些其他的数据库系统中以实现兼容性。因为它是任意列的默认值,它的存在就像噪声一样。

Constraint Naming

SQL标准规定在包含表或域的模式范围内表和域的约束必须具有唯一的名称。 PostgreSQL是比较宽松的:它只需要约束名称在附加到特定表或域的约束之间是唯一的。 但是,对于基于索引的约束(UNIQUE,PRIMARY KEY, and EXCLUDEconstraints), 这个特别的自由度并不存在,因为关联的索引被命名为与约束相同的名称,并且索引名称在相同模式的所有关系中必须是唯一的。

当前,PostgreSQL没有记录NOT NULL约束的名称,因此它们不受唯一性限制的影响。 这在将来的版本中可能会改变。

继承

通过INHERITS子句的多继承是一种PostgreSQL的语言扩展。SQL:1999 以及之后的标准使用一种不同的语法和不同的语义定义了单继承。SQL:1999-风格的继承还没有被PostgreSQL

零列表

PostgreSQL允许创建一个没有列的表(例如CREATE TABLE foo();)。这是一个对于 SQL 标准的扩展,它不允许零列表。零列表本身并不是很有用,但是不允许它们会为ALTER TABLE DROP COLUMN带来奇怪的特殊情况,因此忽略这种规则限制看起来更加整洁。

多个标识列

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

Generated Columns

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

LIKE 子句

虽然 SQL 标准中有一个LIKE子句,但是PostgreSQL接受的很多LIKE子句选项却不在标准中,并且有些标准中的选项也没有被PostgreSQL实现。

WITH子句

WITH子句是一个PostgreSQL扩展,存储参数不在标准中。

表空间

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

类型化的表

类型化的表实现了 SQL 标准的一个子集。根据标准,一个类型化的表具有与底层组合类型相对应的列,以及其他的自引用列PostgreSQL不显式支持自引用列。

PARTITION BY 子句

PARTITION BY子句是PostgreSQL的一个扩展。

PARTITION OF 子句

PARTITION OF子句PostgreSQL的一个扩展。

参见

ALTER TABLE, DROP TABLE, CREATE TABLE AS, CREATE TABLESPACE, CREATE TYPE