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 [ NO INHERIT ] |
NULL |
CHECK ( expression ) [ NO INHERIT ] |
DEFAULT default_expr |
GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] |
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 ] [ ENFORCED | NOT ENFORCED ]
and table_constraint is:
[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
NOT NULL column_name [ NO INHERIT ] |
UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters |
PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters |
EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ]
[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]
and like_option is:
{ INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
and partition_bound_spec is:
IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )
index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:
[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]
exclude_element in an EXCLUDE constraint is:
{ column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
referential_action in a FOREIGN KEY/REFERENCES constraint is:
{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }
CREATE TABLE 将在当前数据库中创建一个新的、初始为空的表。该表归发出该命令的用户所有。
如果给出了模式名(例如 CREATE TABLE myschema.mytable ...),则表将在指定模式中创建。 否则,它将在当前模式中创建。临时表存在于一个特殊模式中,因此创建临时表时不能给出模式名。 表名必须与同一模式中任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。
CREATE TABLE 还会自动创建一种数据类型,用以表示与该表一行对应的复合类型。因此,表名不能与同一模式中任何已有数据类型同名。
可选的约束子句指定插入或更新要成功时,新行或更新后的行必须满足的约束(测试)。约束是一种 SQL 对象,可用多种方式帮助定义表中允许的值集合。
定义约束有两种方式:表约束和列约束。列约束作为列定义的一部分定义。表约束则不绑定到特定列,并且可以涵盖多个列。每个列约束也都可以写成表约束;当约束只影响一列时,列约束只是一种书写上的方便。
要创建表,必须分别对所有列类型或 OF 子句中的类型拥有 USAGE 权限。
TEMPORARY or TEMP #如果指定该选项,表将创建为临时表。 临时表会在会话结束时自动删除,或者也可在当前事务结束时删除(见下文 ON COMMIT)。 默认的 search_path 会首先包含临时模式,因此在临时表存在期间,除非使用带模式限定的名称引用,否则不会在新计划中选中同名的现有永久表。 在临时表上创建的任何索引也都会自动成为临时索引。
自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE。
可以在 TEMPORARY 或 TEMP 前写 GLOBAL 或 LOCAL。这在当前的 PostgreSQL 中没有区别,而且已废弃;见下文 Compatibility。
UNLOGGED #如果指定该选项,表将创建为不记录日志表。写入不记录日志表的数据不会写入预写式日志(见 Chapter 28),因此它们比普通表快得多。不过,它们不具备崩溃安全性:在崩溃或非正常关闭后,不记录日志表会被自动截断。不记录日志表的内容也不会复制到备库。在不记录日志表上创建的任何索引也都会自动成为不记录日志的。
如果指定该选项,与不记录日志表一起创建的任何序列(用于标识列或 serial 列)也会创建为不记录日志的。
这种形式不支持分区表。
IF NOT EXISTS #如果已存在同名关系,则不抛出错误,而是发出一条提示。注意,这并不保证现有关系与本应创建出的关系有任何相似之处。
table_name #要创建的表名(可选地带模式限定)。
OF type_name #创建一个类型化表,其结构取自指定的独立复合类型(即通过 CREATE TYPE 创建的类型),同时该表自身也会生成一个新的复合类型。该表会依赖于所引用的类型,这意味着对该类型执行级联的 ALTER 或 DROP 操作会传播到该表。
类型化表的列名和数据类型始终与其派生类型相同,因此不能再指定额外的列。但 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 可提高超大 text 和 bytea 值上的子串操作速度,但代价是占用更多存储空间。详见 Section 65.2。
COMPRESSION compression_method #COMPRESSION 子句设置列的压缩方法。 压缩仅支持变宽数据类型,并且只会在列的存储模式为 main 或 extended 时使用。 (有关列存储模式的信息,见 ALTER TABLE。) 为分区表设置该属性没有直接影响,因为此类表自身不存储数据,但新创建的分区会继承该配置值。 支持的压缩方法是 pglz 和 lz4。 (只有在构建 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 操作符类,哈希分区则需要 hash 操作符类。 如果未显式指定操作符类,将使用相应类型的默认操作符类;若不存在默认操作符类,则会报错。 使用哈希分区时,所用操作符类必须实现支持函数 2(详见 Section 36.16.3)。
分区表被划分为多个子表(称为分区),它们使用单独的 CREATE TABLE 命令创建。 分区表本身为空。插入到该表的数据行会根据分区键中列或表达式的值被路由到相应分区。 如果没有现有分区与新行中的值匹配,就会报错。
有关表分区的更多讨论,请参阅 Section 5.12。
PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT } #将该表创建为指定父表的分区。 可以使用 FOR VALUES 将其创建为特定值的分区,也可以使用 DEFAULT 创建为默认分区。 父表上已有的任何索引、约束和用户定义的行级触发器都会克隆到新分区上。
partition_bound_spec 必须对应于父表的分区方法和分区键,并且不能与该父表的任何现有分区重叠。 带 IN 的形式用于列表分区,带 FROM 和 TO 的形式用于范围分区,带 WITH 的形式用于哈希分区。
partition_bound_expr 是任何无变量表达式(不允许子查询、窗口函数、聚合函数和集返回函数)。 它的数据类型必须与相应分区键列的数据类型相匹配。 表达式在表创建时只计算一次,因此它甚至可以包含易失性表达式,例如 。CURRENT_TIMESTAMP
在创建列表分区时,可以指定 NULL,表示该分区允许分区键列为空。 但是,对于给定的父表,这样的列表分区不能多于一个。NULL 不能用于范围分区。
创建范围分区时,由 FROM 指定的下界是包含边界,而由 TO 指定的上界是不包含边界。 也就是说,FROM 列表中指定的值是该分区相应分区键列的有效值,而 TO 列表中的值不是。 请注意,必须根据按行比较的规则来理解这一点(Section 9.25.5)。 例如,给定 PARTITION BY RANGE (x,y),分区边界 FROM (1, 2) TO (3, 4) 允许 x=1 且任意 y>=2, x=2 且任意非空 y,以及 x=3 且任意 y<4。
在创建范围分区时,可以使用特殊值 MINVALUE 和 MAXVALUE 表示该列值没有下界或上界。例如,使用 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" 开头的所有行。
请注意,如果 MINVALUE 或 MAXVALUE 用于分区边界中的某一列,则后续所有列都必须使用相同的值。 例如,(10, MINVALUE, 0) 不是有效边界;应写成 (10, MINVALUE, MINVALUE)。
还要注意,某些元素类型(如 timestamp)具有 "infinity" 的概念,那只是另一种可存储的值。这不同于 MINVALUE 和 MAXVALUE,后两者并非可存储 的实际值,而只是表示值无界的方式。MAXVALUE 可以视为大于任何 其他值,包括 "infinity";MINVALUE 可以视为小于任何 其他值,包括 "minus infinity"。因此,范围 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 #会复制被复制列定义的默认表达式。否则默认表达式不会复制,因此新表中复制出的列默认值为 null。 注意,复制那些调用数据库修改函数(如 nextval)的默认值,可能在原表与新表之间建立功能性关联。
INCLUDING GENERATED #会复制被复制列定义中的生成表达式以及 STORED/VIRTUAL 的选择。默认情况下,新列将是常规基表列。
INCLUDING IDENTITY #会复制被复制列定义中的任何标识规范。新表的每个标识列都会创建一个新序列,它与旧表关联的序列相互独立。
INCLUDING INDEXES #原表上的索引、PRIMARY KEY、UNIQUE 和 EXCLUDE 约束都会在新表上创建。 新索引和约束的名称会按默认规则选择,而不考虑原始名称。(这种行为可避免新索引因名称重复而失败。)
INCLUDING STATISTICS #扩展统计信息将复制到新表。
INCLUDING STORAGE #会复制被复制列定义的 STORAGE 设置。 默认行为是不复制 STORAGE 设置,因此新表中复制出的列将使用类型特定的默认设置。 关于 STORAGE 设置的更多信息,请参见 Section 65.2。
INCLUDING ALL #INCLUDING ALL 是选择所有可用单项选项的缩写形式。 (可以在 INCLUDING ALL 之后再写单独的 EXCLUDING 子句,以选中除某些特定选项之外的全部选项。)
LIKE 子句也可用于从视图、外部表或复合类型复制列定义。不适用的选项(例如从视图复制 INCLUDING INDEXES)会被忽略。
CONSTRAINT constraint_name #列约束或表约束的可选名称。如果约束被违反,错误消息中会包含该约束名,因此诸如 col must be positive 这样的约束名可以向客户端应用传达有用的约束信息。(若约束名中包含空格,则需要用双引号指定。)如果未指定约束名,系统会生成一个。
NOT NULL [ NO INHERIT ] #该列不允许包含空值。
标记为 NO INHERIT 的约束不会传播到子表。
NULL #该列允许包含空值。这是默认情况。
该子句仅为兼容非标准 SQL 数据库而提供,不建议在新应用中使用。
CHECK ( expression ) [ NO INHERIT ] #CHECK 子句指定一个产生布尔结果的表达式。要使插入或更新成功,新行或更新后的行必须满足该表达式。计算结果为 TRUE 或 UNKNOWN 的表达式视为成功。如果插入或更新操作中的任何一行得到 FALSE 结果,就会抛出错误异常,并且插入或更新不会修改数据库。作为列约束指定的检查约束只应引用该列的值,而出现在表约束中的表达式可以引用多个列。
当前,CHECK 表达式不能包含子查询,也不能引用当前行的列之外的变量(参见 Section 5.5.1)。可以引用系统列 tableoid,但不能引用其他系统列。
一个被标记为NO INHERIT的约束将不会传播到子表。
当一个表有多个 CHECK 约束时,在检查完 NOT NULL 约束之后,会按名称的字母顺序对每一行进行检查。(9.5 之前的 PostgreSQL 版本并不保证 CHECK 约束的特定触发顺序。)
DEFAULT default_expr #DEFAULT 子句为其所在列指定默认数据值。该值是一个不含变量的表达式(特别是,不允许引用当前表中的其他列)。子查询也不允许。 默认值表达式的数据类型必须匹配列的数据类型。
默认值表达式会用于任何未为该列指定值的插入操作。如果一列没有默认值,则默认值为 null。
GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] #此子句将列创建为生成列。列不可写入,读取时会返回指定表达式的结果。
指定 VIRTUAL 时,列会在读取时计算且不占用存储;指定 STORED 时,列会在写入时计算并存储在磁盘上。默认是 VIRTUAL。
生成表达式可以引用表中的其他列,但不能引用其他生成的列。使用的任何函数和操作符都必须是不可变的。不允许引用其他表。
虚拟生成列不能使用用户定义类型,且其生成表达式不得引用用户定义函数或类型,也就是只能使用内置函数或类型。此限制也包含间接使用(例如操作符或类型转换背后的函数或类型)。该限制不适用于存储型生成列。
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] #该子句将列创建为标识列。 它会隐式附带一个序列,并且在新插入的行中,该列会自动取得分配给它的序列值。 这种列会隐式带有 NOT NULL 约束。
ALWAYS 和 BY DEFAULT 子句决定在 INSERT 和 UPDATE 命令中如何处理用户显式指定的值。
在 INSERT 命令中,如果选择了 ALWAYS,则仅当 INSERT 语句指定 OVERRIDING SYSTEM VALUE 时 才接受用户指定的值。如果选择了 BY DEFAULT,则用户指定的值优先。 有关详细信息,请参阅 INSERT。(在 COPY 命令中, 无论此设置如何,始终使用用户指定的值。)
在 UPDATE 命令中,如果选择了 ALWAYS, 则把该列更新为除 DEFAULT 之外的任何值都会被拒绝。 如果选择了 BY DEFAULT,则该列可以正常更新。 (UPDATE 命令没有 OVERRIDING 子句。)
可选的 sequence_options 子句可用于覆盖序列参数。可用选项包括 CREATE SEQUENCE 中展示的选项,另外还包括 SEQUENCE NAME 、nameLOGGED 与 UNLOGGED,用于选择序列名称及持久化级别。不指定 SEQUENCE NAME 时,系统会为该序列选择一个未使用名称。不指定 LOGGED 或 UNLOGGED 时,序列将与表具有相同的持久化级别。
UNIQUE [ NULLS [ NOT ] DISTINCT ](列约束)UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) [ INCLUDE ( column_name [, ...]) ](表约束) #UNIQUE 约束指定表中一列或多列组成的一组只能包含唯一值。 表级唯一约束的行为与列级唯一约束相同,只是它还能跨越多列。因此,该约束 要求任意两行在这些列中至少有一列不同。
如果为最后一列指定了 WITHOUT OVERLAPS 选项,则该列检查的 是是否重叠,而不是是否相等。在这种情况下,只要重复值在 WITHOUT OVERLAPS 列上不发生重叠,约束中的其他列就允许重 复。(如果该列是日期或时间戳范围,这有时被称为时态键;但 PostgreSQL 允许在任意基础类型上定义范围。) 实际上,这种约束是通过 EXCLUDE 约束而不是 UNIQUE 约束来强制的。例如, UNIQUE (id, valid_at WITHOUT OVERLAPS) 的行为类似于 EXCLUDE USING GIST (id WITH =, valid_at WITH &&)。 WITHOUT OVERLAPS 列必须是范围类型或多范围类型,且不允许 为空范围或空多范围。该约束中不带 WITHOUT OVERLAPS 的列可以 是任何可在 GiST 索引中按相等性比较的类型。默认仅支持范围类型,但可通过安装 btree_gist 扩展来使用其他类型(这也是该特性的预期用法)。
就唯一约束而言,空值不被视为相等,除非指定了 NULLS NOT DISTINCT。
每个唯一约束都应引用一组列,这组列应不同于该表上任何其他唯一约束或 主键约束所引用的列集合。(否则,冗余的唯一约束将被丢弃。)
在为多级分区层次结构建立唯一约束时,目标分区表分区键中的所有列,以及 其所有后代分区表分区键中的所有列,都必须包含在约束定义中。
添加唯一约束会自动在约束所用的列或列组上创建唯一 B-树索引;但如果该约束 包含 WITHOUT OVERLAPS 子句,则会使用 GiST 索引。所创建 的索引与该唯一约束同名。
可选的 INCLUDE 子句会向该索引添加一个或多个仅作为 “payload” 的列:对这些列不强制唯一性,而且该索引也不能据此 进行搜索。不过,它们可以通过仅索引扫描取回。注意,尽管约束不在包含列上 强制执行,它仍然依赖于这些列。因此,对这类列执行某些操作(例如 DROP COLUMN)可能导致约束和索引被级联删除。
PRIMARY KEY(列约束)PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) [ INCLUDE ( column_name [, ...]) ](表约束) #PRIMARY KEY 约束指定表的一列或多列只能包含唯一 (不重复)且非空的值。无论作为列约束还是表约束,一个表都只能指定一个 主键。
主键约束所引用的列集合应不同于同一表上定义的任何唯一约束所引用的列集 合。(否则,该唯一约束是冗余的,会被丢弃。)
PRIMARY KEY 强制的数据约束与 UNIQUE 和 NOT NULL 的组合相同。不 过,将一组列标识为主键还会为模式设计提供元数据,因为主键意味着其他表可以 将这组列作为行的唯一标识符来依赖。
放在分区表上时,PRIMARY KEY 约束与前面描述的 UNIQUE 约束有相同的限制。
添加 PRIMARY KEY 约束会自动在约束所用的列或列组上创建 唯一 B-树索引;如果指定了 WITHOUT OVERLAPS,则会创建 GiST 索引。
可选的 INCLUDE 子句会向该索引添加一个或多个仅作为 “payload” 的列:对这些列不强制唯一性,而且该索引也不能据此 进行搜索。不过,它们可以通过仅索引扫描取回。注意,尽管约束不在包含列上 强制执行,它仍然依赖于这些列。因此,对这类列执行某些操作(例如 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 62);目前这意味着不能使用 GIN。 虽然允许,但在排他约束上使用 B-树或 hash 索引意义不大,因为它们做不到 比普通唯一约束更好的事情。因此,实践中访问方法几乎总会是 GiST 或 SP-GiST。
predicate 允许你只在表的一个 子集上指定排他约束;在内部,这会创建一个部分索引。注意, predicate 周围的圆括号是必需的。
在为多级分区层次结构建立排他约束时,目标分区表分区键中的所有列,以及其 所有后代分区表分区键中的所有列,都必须包含在约束定义中。此外,这些列必 须使用等值操作符进行比较。这些限制保证潜在冲突的行会落在同一分区中。约 束也可以引用不属于任何分区键的其他列,这些列可以使用任何合适的操作符来 比较。
REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ](列约束)FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (表约束) #这些子句指定外键约束,要求新表的一列或多列组成的一组只能包含与被引用 表某一行的被引用列中值相匹配的值。若省略 refcolumn 列表,则使用 reftable 的主键。否则, refcolumn 列表必须引用某个不可延 迟的唯一约束或主键约束的列,或者引用某个非部分唯一索引的列。
如果最后一列标记为 PERIOD,则会按特殊方式处理。非 PERIOD 列按相等性比较(并且至少需要一列),而 PERIOD 列则不会。取而代之的是,只有当被引用表中基于键的 非 PERIOD 部分相匹配的记录,其合并后的 PERIOD 值能够完整覆盖引用记录的 PERIOD 值时,约束才算满足。换言之,该引用在其整个持续区 间内都必须有对应的被引用对象。该列必须是范围类型或多范围类型。此外,被 引用表必须具有用 WITHOUT OVERLAPS 声明的主键或唯一约 束。最后,如果外键包含 PERIOD column_name 说明,则对应的 refcolumn(如果存在)也必须标记 为 PERIOD。如果省略 refcolumn 子句,从而选择 reftable 的主键约束,则该主键的最后一列必须标记为 WITHOUT OVERLAPS。
对于每一对引用列和被引用列,如果它们属于可排序数据类型,则两者的排序规 则要么都必须是确定性的,要么必须完全相同。这样可以确保两列对“相等”具 有一致的定义。
用户必须对被引用表拥有 REFERENCES 权限(对整张表,或对 特定的被引用列)。添加外键约束需要在被引用表上获取 SHARE ROW EXCLUSIVE 锁。注意,不能在临时表和永久表之间 定义外键约束。
插入到引用列中的值会按照给定的匹配类型,与被引用表及其被引用列中的值进 行匹配。共有三种匹配类型:MATCH FULL、 MATCH PARTIAL 和 MATCH SIMPLE (默认值)。MATCH FULL 不允许多列外键中的某一列为 空,除非所有外键列都为空;如果它们都为空,则不要求该行在被引用表中有匹 配行。MATCH SIMPLE 允许任意外键列为空;如果其中任何一 列为空,则不要求该行在被引用表中有匹配行。 MATCH PARTIAL 目前尚未实现。(当然,可以对引用列应用 NOT NULL 约束,以防止出现这些情况。)
此外,当被引用列中的数据发生变化时,会对本表列中的数据执行某些操作。 ON DELETE 子句指定当被引用表中的被引用行被删除时要执行 的操作。同样,ON UPDATE 子句指定当被引用表中的被引用列 被更新为新值时要执行的操作。如果更新了行,但被引用列实际上并未改变,则 不执行任何操作。引用动作作为数据更改命令的一部分执行,即使该约束是延迟 的也一样。每个子句可用的操作如下:
NO ACTION #如果删除或更新会导致外键约束违规,则产生错误。如果约束被延迟,且到 约束检查时仍然存在任何引用行,就会产生此错误。 这是默认操作。
RESTRICT #如果待删除或更新的行在引用表中有匹配行,则产生错误。即使操作完成后 的状态并不违反外键约束,也会阻止该操作。特别地,它会阻止将被引用行 更新为“值不同但比较相等”的情况。(但不会阻止把列更新为相同值的 “无操作”更新。)
对于时态外键,该选项不受支持。
CASCADE #分别删除任何引用已删除行的行,或将引用列的值更新为被引用列的新值。
对于时态外键,该选项不受支持。
SET NULL [ ( column_name [, ... ] ) ] #将全部引用列,或指定的引用列子集,设置为空值。只有 ON DELETE 动作才能指定列子集。
对于时态外键,该选项不受支持。
SET DEFAULT [ ( column_name [, ... ] ) ] #将全部引用列,或指定的引用列子集,设置为其默认值。只有 ON DELETE 动作才能指定列子集。(如果默认值不是空 值,则被引用表中必须有一行与这些默认值匹配,否则该操作会失败。)
对于时态外键,该选项不受支持。
如果被引用列经常发生变化,那么最好在引用列上添加一个索引,以便更高效地 执行与该外键约束相关的引用动作。
DEFERRABLENOT DEFERRABLE #该子句控制约束是否可延迟。不可延迟的约束会在每条命令之后立即检查。可 延迟约束的检查可以推迟到事务结束时(使用 SET CONSTRAINTS 命令)。NOT DEFERRABLE 是默认值。当前,只有 UNIQUE、PRIMARY KEY、 EXCLUDE 和 REFERENCES(外键)约束接受 该子句。NOT NULL 和 CHECK 约束不可延 迟。 注意在包含 ON CONFLICT 子句的 INSERT 语句中,可延迟约束不能用作冲突仲裁器。
INITIALLY IMMEDIATEINITIALLY DEFERRED #如果约束可延迟,该子句指定默认的约束检查时间。如果约束是 INITIALLY IMMEDIATE,则会在每条语句之后检查。这是默 认值。如果约束是 INITIALLY DEFERRED,则只会在事务结束 时检查。约束检查时间可以用 SET CONSTRAINTS 命令修改。
ENFORCEDNOT ENFORCED #当约束为 ENFORCED 时,数据库系统会在适当时机检查该约束(按需要在每条语句后或事务结束时),这是默认行为。若约束为 NOT ENFORCED,数据库系统将不再检查该约束,改由应用代码保证约束成立。对于不影响结果正确性的优化决策,数据库系统仍可能假定数据满足该约束。
NOT ENFORCED 约束可作为文档用途,适用于运行时检查约束代价过高的场景。
当前该能力仅支持外键约束与 CHECK 约束。
USING method #该可选子句指定存储新表内容所用的表访问方法;该方法必须是类型为 TABLE 的访问方法。详见 Chapter 61。如果未 指定此选项,则会为新表选择默认表访问方法。详见 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 #该子句允许选择与 UNIQUE、PRIMARY KEY 或 EXCLUDE 约束相关联的索引要创建在哪个表空间中。若未 指定,则参考 default_tablespace;如果该表是临时表, 则参考 temp_tablespaces。
WITH 子句可以为表以及与 UNIQUE、 PRIMARY KEY 或 EXCLUDE 约束关联的索引 指定存储参数。索引的存储参数已在 CREATE INDEX 中介绍。当前可用于表的存储参数列在下文。 对于其中许多参数,如下所示,还存在一个同名且带 toast. 前缀的附加参数,用于控制该表的二级 TOAST 表(如果有)的行为(更多有关 TOAST 的信息见 Section 65.2)。如果设置了表参数值,而对应的 toast. 参数未设置,则 TOAST 表将使用该表的参数值。不支持为 分区表指定这些参数,但可以为单独的叶子分区指定。
fillfactor (integer) #表的填充因子是介于 10 到 100 之间的百分比。100(完全填充)是默认值。 当指定较小的填充因子时,INSERT 操作只会把表页填充到 指定百分比;每页剩余的空间则预留给更新该页上的行。这使得 UPDATE 有机会将更新后的行副本放在与原始行相同的页 上,这比放在不同页上更高效,也更有可能发生 堆内元组更新。对于条目永远不会更新的表, 完全填充是最佳选择;但对频繁更新的表来说,较小的填充因子更合适。不能为 TOAST 表设置此参数。
toast_tuple_target (integer) #toast_tuple_target 指定在尝试压缩和/或将长列值移入 TOAST 表之前所需的最小元组长度,同时也是一旦开始 TOAST 化后试图将长度 缩减到的目标长度。这会影响标记为 External(用于移动)、Main(用于压缩) 或 Extended(用于两者)的列,并且只适用于新元组。对现有行没有影响。默认 情况下,该参数被设置为至少允许每个块容纳 4 个元组,在默认块大小下即为 2040 字节。有效值介于 128 字节与(块大小减去页头)之间,默认上限为 8160 字节。对非常短或非常长的行,修改该值可能没有帮助。注意,默认设置通 常已经接近最佳,某些情况下设置该参数可能产生负面影响。不能为 TOAST 表设 置此参数。
parallel_workers (integer) #该参数设置在对该表执行并行扫描时可用于辅助扫描的工作进程数量。若未设置, 系统会根据关系大小决定一个值。规划器或使用并行扫描的实用命令实际选择的 工作进程数量可能更少,例如可能受 max_worker_processes 设置所限。
autovacuum_enabled, toast.autovacuum_enabled (boolean) #为特定表启用或禁用自动清理守护进程。如果为真,自动清理守护进程将按照 Section 24.1.6 中讨论的规则,在该表上执行自动 VACUUM 和/或 ANALYZE 操作。如果为 假,则该表不会被自动清理,但为了防止事务 ID 回卷,仍可能对其执行自动清 理。有关回卷防护的更多信息,见 Section 24.1.5。 注意,如果 autovacuum 参数为假,则自动清理守护进程 根本不会运行(防止事务 ID 回卷的情况除外);为单独表设置存储参数也不会 覆盖这一点。因此,显式将此存储参数设为 true 往往意义不 大,设为 false 才更有用。
vacuum_index_cleanup, toast.vacuum_index_cleanup (enum) #强制或禁用在该表上执行 VACUUM 时的索引清理。默认值 为 AUTO。设为 OFF 时禁用索引清理, 设为 ON 时启用,设为 AUTO 时,则每次 运行 VACUUM 都会动态决定。动态行为允许 VACUUM 避免为了移除很少的死元组而无谓地扫描索引。强 制禁用全部索引清理可以显著加快 VACUUM,但如果表修改频 繁,也可能导致索引严重膨胀。若在 VACUUM 中指定了 INDEX_CLEANUP 参数,则会覆盖此选项的值。
vacuum_truncate, toast.vacuum_truncate (boolean) #启用或禁用 vacuum 尝试截去该表末尾的空页。默认值为 true。若为 true, VACUUM 和 autovacuum 都会执行截断,并将被截断页面占用的磁盘空间返还给操作系统。注意,截断操作需要对表持有 ACCESS EXCLUSIVE 锁。若在 VACUUM 中指定了 TRUNCATE 参数,则会覆盖此选项的值。
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_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) #将该表声明为逻辑复制用途的附加目录表。详见 Section 47.6.2。不能为 TOAST 表设置此参数。
PostgreSQL为每一个唯一约束和主键约束创建一个索引来强制唯一性。因此,没有必要显式地为主键列创建一个索引(详见CREATE INDEX)。
在当前的实现中,唯一约束和主键不会被继承。这使得继承与唯一约束的组合相当不实用。
一个表不能有超过 1600 列(实际上,由于元组长度限制,有效的限制通常更低)。
创建表films和表distributors:
CREATE TABLE films (
code char(5) CONSTRAINT firstkey PRIMARY KEY,
title varchar(40) NOT NULL,
did integer NOT NULL,
date_prod date,
kind varchar(10),
len interval hour to minute
);
CREATE TABLE distributors (
did integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
name varchar(40) NOT NULL CHECK (name <> '')
);
创建一个带二维数组列的表:
CREATE TABLE array_int (
vector int[][]
);
为表films定义一个唯一表约束。唯一表约束可以定义在表的一列或多列上:
CREATE TABLE films (
code char(5),
title varchar(40),
did integer,
date_prod date,
kind varchar(10),
len interval hour to minute,
CONSTRAINT production UNIQUE(date_prod)
);
定义一个列检查约束:
CREATE TABLE distributors (
did integer CHECK (did > 100),
name varchar(40)
);
定义一个表检查约束:
CREATE TABLE distributors (
did integer,
name varchar(40),
CONSTRAINT con1 CHECK (did > 100 AND name <> '')
);
为表films定义一个主键表约束:
CREATE TABLE films (
code char(5),
title varchar(40),
did integer,
date_prod date,
kind varchar(10),
len interval hour to minute,
CONSTRAINT code_title PRIMARY KEY(code,title)
);
为表distributors定义一个主键约束。下面的两个示例是等价的,第一个使用表约束语法,第二个使用列约束语法:
CREATE TABLE distributors (
did integer,
name varchar(40),
PRIMARY KEY(did)
);
CREATE TABLE distributors (
did integer PRIMARY KEY,
name varchar(40)
);
为列name指定一个字面常量默认值,将列did的默认值设为从某个序列对象中取下一个值,并让modtime的默认值为插入该行的时间:
CREATE TABLE distributors (
name varchar(40) DEFAULT 'Luso Films',
did integer DEFAULT nextval('distributors_serial'),
modtime timestamp DEFAULT current_timestamp
);
在表distributors上定义两个NOT NULL列约束,其中一个显式指定了名称:
CREATE TABLE distributors (
did integer CONSTRAINT no_null NOT NULL,
name varchar(40) NOT NULL
);
为name列定义一个唯一约束:
CREATE TABLE distributors (
did integer,
name varchar(40) UNIQUE
);
同样的唯一约束用表约束指定:
CREATE TABLE distributors (
did integer,
name varchar(40),
UNIQUE(name)
);
创建同样的表,并为该表及其唯一索引都指定 70% 的填充因子:
CREATE TABLE distributors (
did integer,
name varchar(40),
UNIQUE(name) WITH (fillfactor=70)
)
WITH (fillfactor=70);
创建表circles,并添加一个排他约束以防任意两个圆重叠:
CREATE TABLE circles (
c circle,
EXCLUDE USING gist (c WITH &&)
);
在表空间diskvol1中创建表cinemas:
CREATE TABLE cinemas (
id serial,
name text,
location text
) TABLESPACE diskvol1;
创建一个复合类型和一个类型化表:
CREATE TYPE employee_type AS (name text, salary numeric);
CREATE TABLE employees OF employee_type (
PRIMARY KEY (name),
salary WITH OPTIONS DEFAULT 1000
);
创建一个范围分区表:
CREATE TABLE measurement (
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate);
创建一个在分区键中包含多个列的范围分区表:
CREATE TABLE measurement_year_month (
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate));
创建列表分区表:
CREATE TABLE cities (
city_id bigserial not null,
name text not null,
population bigint
) PARTITION BY LIST (left(lower(name), 1));
创建哈希分区表:
CREATE TABLE orders (
order_id bigint not null,
cust_id bigint not null,
status text
) PARTITION BY HASH (order_id);
创建范围分区表的分区:
CREATE TABLE measurement_y2016m07
PARTITION OF measurement (
unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');
使用分区键中的多个列创建范围分区表的几个分区:
CREATE TABLE measurement_ym_older
PARTITION OF measurement_year_month
FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);
CREATE TABLE measurement_ym_y2016m11
PARTITION OF measurement_year_month
FOR VALUES FROM (2016, 11) TO (2016, 12);
CREATE TABLE measurement_ym_y2016m12
PARTITION OF measurement_year_month
FOR VALUES FROM (2016, 12) TO (2017, 01);
CREATE TABLE measurement_ym_y2017m01
PARTITION OF measurement_year_month
FOR VALUES FROM (2017, 01) TO (2017, 02);
创建列表分区表的分区:
CREATE TABLE cities_ab
PARTITION OF cities (
CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b');
创建一个本身还要进一步分区的列表分区表分区,然后再向其添加一个分区:
CREATE TABLE cities_ab
PARTITION OF cities (
CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population);
CREATE TABLE cities_ab_10000_to_100000
PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);
创建哈希分区表的分区:
CREATE TABLE orders_p1 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF orders
FOR VALUES WITH (MODULUS 4, REMAINDER 3);
创建默认分区:
CREATE TABLE cities_partdef
PARTITION OF cities DEFAULT;
CREATE TABLE 命令符合 SQL 标准,但有下 列例外。
尽管 CREATE TEMPORARY TABLE 的语法看起来类似于 SQL 标 准,但其效果并不相同。按标准,临时表只需定义一次,并会自动存在于每个需 要它的会话中(内容初始为空)。而 PostgreSQL 要求 每个会话都为每个要使用的临时表发出自己的 CREATE TEMPORARY TABLE 命令。这使不同会话可以出于不同目 的使用相同的临时表名;而标准做法则要求给定临时表名的所有实例都必须具有 相同的表结构。
标准对临时表行为的定义在实践中被广泛忽略。PostgreSQL 在这一点上的行为与多种其他 SQL 数据库相似。
SQL 标准还区分全局和局部临时表,其中局部临时表在每个会话内的每个 SQL 模 块中都有独立的内容集合,但其定义仍在多个会话之间共享。由于 PostgreSQL 不支持 SQL 模块,这一区别在 PostgreSQL 中没有意义。
出于兼容性考虑,PostgreSQL 接受在临时表声明中使 用 GLOBAL 和 LOCAL 关键字,但它们目前 没有效果。不鼓励使用这些关键字,因为未来版本的 PostgreSQL 可能会采用更符合标准的解释。
临时表的 ON COMMIT 子句也与 SQL 标准相似,但存在一些差 异。如果省略 ON COMMIT 子句,SQL 规定默认行为是 ON COMMIT DELETE ROWS。然而, PostgreSQL 中的默认行为是 ON COMMIT PRESERVE ROWS。SQL 中不存在 ON COMMIT DROP 选项。
当 UNIQUE 或 PRIMARY KEY 约束不可延 迟时,只要有行被插入或修改,PostgreSQL 就会立刻 检查唯一性。SQL 标准规定应只在语句结束时强制唯一性;例如,当单个命令会更 新多个键值时,这两者就会产生差异。若要获得符合标准的行为,应将约束声明为 DEFERRABLE 但不延迟(即 INITIALLY IMMEDIATE)。注意,这可能明显慢于立即检查唯一 性。
SQL 标准规定,CHECK 列约束只能引用其所作用的列;只有 CHECK 表约束才能引用多列。 PostgreSQL 并不强制这一限制;它对列检查约束和表 检查约束一视同仁。
EXCLUDE 约束EXCLUDE 约束类型是 PostgreSQL 的扩展。
在外键动作 SET DEFAULT 和 SET NULL 中指定列列表的能力,是 PostgreSQL 的扩展。
外键约束可以引用唯一索引的列,而不仅限于主键或唯一约束的列,这也是 PostgreSQL 的扩展。
NULL “约束”NULL “约束”(实际上并不是约束)是 PostgreSQL 对 SQL 标准的扩展;它也被其他一些数 据库系统采纳,以便兼容(以及与对称的 NOT NULL 约束保持一 致)。由于它本来就是任意列的默认值,所以它的存在只是噪声。
SQL 标准规定,在包含表或域的模式范围内,表约束和域约束都必须具有唯一名 称。PostgreSQL 较为宽松:它只要求约束名称在附加 到特定表或域的约束之间唯一。不过,对于基于索引的约束( UNIQUE、PRIMARY KEY 和 EXCLUDE 约束)就没有这种额外自由,因为关联索引与约束同 名,而索引名称在同一模式内的所有关系之间必须唯一。
通过 INHERITS 子句实现的多重继承是 PostgreSQL 的语言扩展。SQL:1999 及后续标准使用不同的语法和语义定义了单继承。PostgreSQL 尚不支持 SQL:1999 风格的继承。
PostgreSQL 允许创建没有列的表(例如 CREATE TABLE foo();)。这是对 SQL 标准的扩展,标准不允许 零列表。零列表本身并不十分有用,但若禁止它们,就会让 ALTER TABLE DROP COLUMN 出现奇怪的特殊情况,因此忽略这 一规范限制看起来更整洁。
PostgreSQL 允许一个表拥有多个标识列。 该标准指定一个表最多只能有一个标识列。 这主要是为了给模式更改或迁移提供更大的灵活性。 请注意,INSERT 命令仅支持一个适用于整个语句的覆盖子 句,因此对行为不同的多个标识列支持并不好。
STORED 和 VIRTUAL 选项都不是标准的一部分,但其他 SQL 实现也会使用。SQL 标准并不规定生成列的存储方式。
LIKE 子句虽然 SQL 标准中存在 LIKE 子句,但 PostgreSQL 接受的许多 LIKE 选项并不在标准中,而标准中的某些选项又没有被 PostgreSQL 实现。
WITH 子句WITH 子句是 PostgreSQL 的扩 展;存储参数不属于标准内容。
PostgreSQL 的表空间概念不是标准的一部分。因此, TABLESPACE 和 USING INDEX TABLESPACE 子句都是扩展。
类型化表实现了 SQL 标准的一个子集。按照标准,类型化表除了具有与底层组合 类型相对应的列之外,还应有一个额外的“自引用列”。 PostgreSQL 不显式支持自引用列。
PARTITION BY 子句PARTITION BY 子句是 PostgreSQL 的扩展。
PARTITION OF 子句PARTITION OF 子句是 PostgreSQL 的扩展。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。