SQL COMMAND · 表与视图
CREATE TABLE
定义一个新表
CREATE表与视图引入 10(基线)现存至 20 devel8 次语法变更
- 动词
CREATE- 对象
TABLE- 分组
- 表与视图
- 引入版本
- 10(基线)
- 状态
- 现存
- 语法变更次数
- 8
- 手册小节数
- 6
版本轨迹
相对 PostgreSQL 17:语法概要新增 10 行,移除 0 行。
语法铁道图 PostgreSQL 18
沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。
CREATE TABLE · 语法 2
CREATE TABLE · 语法 3
column_constraint
table_constraint
like_option
partition_bound_spec
index_parameters
exclude_element
referential_action
语法概要
相对 PostgreSQL 17 新增 10 行,移除 0 行;新增行以绿色标记。
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ]table_name( [ {column_namedata_type[ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSIONcompression_method] [ COLLATEcollation] [column_constraint[ ... ] ] |table_constraint| LIKEsource_table[like_option... ] } [, ... ] ] ) [ INHERITS (parent_table[, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( {column_name| (expression) } [ COLLATEcollation] [opclass] [, ... ] ) ] [ USINGmethod] [ WITH (storage_parameter[=value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACEtablespace_name] CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ]table_nameOFtype_name[ ( {column_name[ WITH OPTIONS ] [column_constraint[ ... ] ] |table_constraint} [, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( {column_name| (expression) } [ COLLATEcollation] [opclass] [, ... ] ) ] [ USINGmethod] [ WITH (storage_parameter[=value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACEtablespace_name] CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ]table_namePARTITION OFparent_table[ ( {column_name[ WITH OPTIONS ] [column_constraint[ ... ] ] |table_constraint} [, ... ] ) ] { FOR VALUESpartition_bound_spec| DEFAULT } [ PARTITION BY { RANGE | LIST | HASH } ( {column_name| (expression) } [ COLLATEcollation] [opclass] [, ... ] ) ] [ USINGmethod] [ WITH (storage_parameter[=value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACEtablespace_name] 其中column_constraint为: [ CONSTRAINTconstraint_name] { NOT NULL [ NO INHERIT ] | NULL | CHECK (expression) [ NO INHERIT ] | DEFAULTdefault_expr| GENERATED ALWAYS AS (generation_expr) [ STORED | VIRTUAL ] | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ (sequence_options) ] | UNIQUE [ NULLS [ NOT ] DISTINCT ]index_parameters| PRIMARY KEYindex_parameters| REFERENCESreftable[ (refcolumn) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action] [ ON UPDATEreferential_action] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] 而table_constraint为: [ CONSTRAINTconstraint_name] { CHECK (expression) [ NO INHERIT ] | NOT NULLcolumn_name[ NO INHERIT ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] (column_name[, ... ] [,column_nameWITHOUT OVERLAPS ] )index_parameters| PRIMARY KEY (column_name[, ... ] [,column_nameWITHOUT OVERLAPS ] )index_parameters| EXCLUDE [ USINGindex_method] (exclude_elementWITHoperator[, ... ] )index_parameters[ WHERE (predicate) ] | FOREIGN KEY (column_name[, ... ] [, PERIODcolumn_name] ) REFERENCESreftable[ (refcolumn[, ... ] [, PERIODrefcolumn] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action] [ ON UPDATEreferential_action] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] 而like_option为: { INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL } 而partition_bound_spec为: IN (partition_bound_expr[, ...] ) | FROM ( {partition_bound_expr| MINVALUE | MAXVALUE } [, ...] ) TO ( {partition_bound_expr| MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUSnumeric_literal, REMAINDERnumeric_literal)UNIQUE、PRIMARY KEY和EXCLUDE约束中的index_parameters为: [ INCLUDE (column_name[, ... ] ) ] [ WITH (storage_parameter[=value] [, ... ] ) ] [ USING INDEX TABLESPACEtablespace_name]EXCLUDE约束中的exclude_element为: {column_name| (expression) } [ COLLATEcollation] [opclass[ (opclass_parameter=value[, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]FOREIGN KEY/REFERENCES约束中的referential_action为: { NO ACTION | RESTRICT | CASCADE | SET NULL [ (column_name[, ... ] ) ] | SET DEFAULT [ (column_name[, ... ] ) ] }
描述
CREATE TABLE 将在当前数据库中创建一个新的、初始为空的表。该表归发出该命令的用户所有。
如果给出了模式名(例如 CREATE TABLE myschema.mytable ...),则表将在指定模式中创建。否则,它将在当前模式中创建。临时表存在于一个特殊模式中,因此创建临时表时不能给出模式名。表名必须与同一模式中任何其他关系(表、序列、索引、视图、物化视图或外部表)的名称不同。
CREATE TABLE 还会自动创建一种数据类型,用以表示与该表一行对应的复合类型。因此,表名不能与同一模式中任何已有数据类型同名。
可选的约束子句指定插入或更新要成功时,新行或更新后的行必须满足的约束(测试)。约束是一种 SQL 对象,可用多种方式帮助定义表中允许的值集合。
定义约束有两种方式:表约束和列约束。列约束作为列定义的一部分定义。表约束则不绑定到特定列,并且可以涵盖多个列。每个列约束也都可以写成表约束;当约束只影响一列时,列约束只是一种书写上的方便。
要创建表,必须分别对所有列类型或 OF 子句中的类型拥有 USAGE 权限。
参数
TEMPORARY或TEMP如果指定该选项,表将创建为临时表。临时表会在会话结束时自动删除,或者也可在当前事务结束时删除(见下文
ON COMMIT)。默认的 search_path 会首先包含临时模式,因此在临时表存在期间,除非使用带模式限定的名称引用,否则不会在新计划中选中同名的现有永久表。在临时表上创建的任何索引也都会自动成为临时索引。自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行
ANALYZE。可以在
TEMPORARY或TEMP前写GLOBAL或LOCAL。这在当前的 PostgreSQL 中没有区别,而且已弃用;见下文Compatibility。UNLOGGED如果指定该选项,表将创建为不记录 WAL 的表。写入不记录 WAL 的表的数据不会写入预写式日志(见第 28 章),因此它们比普通表快得多。不过,它们不具备崩溃安全性:在崩溃或非正常关闭后,不记录 WAL 的表会被自动截断。不记录 WAL 的表的内容也不会复制到备库。在不记录 WAL 的表上创建的任何索引也都会自动成为不记录 WAL 的。
如果指定该选项,与不记录 WAL 的表一起创建的任何序列(用于标识列或 serial 列)也会创建为不记录 WAL 的。
这种形式不支持分区表。
IF NOT EXISTS已经存在同名关系时不要抛出错误。这种情况下会发出一个提示。注意,已存在的关系不保证与原本将要创建的关系有任何相似之处。
table_name要创建的表名(可选地带模式限定)。
OFtype_name创建一个类型化表,其结构取自指定的独立复合类型(即通过CREATE TYPE创建的类型),同时该表自身也会生成一个新的复合类型。该表会依赖于所引用的类型,这意味着对该类型执行级联的 ALTER 或 DROP 操作会传播到该表。
类型化表的列名和数据类型始终与其所基于的类型相同,因此不能再指定额外的列。但
CREATE TABLE命令仍可为该表添加默认值和约束,并指定存储参数。column_name要在新表中创建的列名。
data_type该列的数据类型,可以包含数组说明符。有关PostgreSQL支持的数据类型的更多信息,参见第 8 章。
COLLATEcollationCOLLATE子句为列指定排序规则(该列必须属于支持排序规则的数据类型)。如果未指定,则使用列数据类型的默认排序规则。STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT }该形式设置列的存储模式,用于控制该列是以行内形式存储还是存入二级 TOAST 表,以及数据是否压缩。
PLAIN必须用于诸如integer的定长值,表示行内且不压缩。MAIN用于行内且可压缩的数据。EXTERNAL用于行外且不压缩的数据,EXTENDED用于行外且压缩的数据。写成DEFAULT则将存储模式设置为该列数据类型的默认模式。对大多数支持非PLAIN存储的数据类型,默认是EXTENDED。使用EXTERNAL可提高超大text和bytea值上的子串操作速度,但代价是占用更多存储空间。详见第 66.2 节。COMPRESSIONcompression_methodCOMPRESSION子句设置列的压缩方法。压缩仅支持变宽数据类型,并且只会在列的存储模式为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子句指定表的分区策略。这样创建的表称为分区表。括号中的列或表达式列表构成该表的分区键。使用范围分区或 hash 分区时,分区键可以包含多个列或表达式(最多 32 个,但该限制可在构建 PostgreSQL 时调整);而列表分区的分区键必须由单个列或表达式组成。范围分区和列表分区需要 B-树操作符类,hash 分区则需要 hash 操作符类。如果未显式指定操作符类,将使用相应类型的默认操作符类;若不存在默认操作符类,则会报错。使用 hash 分区时,所用操作符类必须实现支持函数 2(详见第 36.16.3 节)。
分区表被划分为多个子表(称为分区),它们使用单独的
CREATE TABLE命令创建。分区表本身为空。插入到该表的数据行会根据分区键中列或表达式的值被路由到相应分区。如果没有现有分区与新行中的值匹配,就会报错。有关表分区的更多讨论,请参阅第 5.12 节。
PARTITION OFparent_table{ FOR VALUESpartition_bound_spec| DEFAULT }将该表创建为指定父表的分区。可以使用
FOR VALUES将其创建为特定值的分区,也可以使用DEFAULT创建为默认分区。父表上已有的任何索引、约束和用户定义的行级触发器都会克隆到新分区上。partition_bound_spec必须对应于父表的分区方法和分区键,并且不能与该父表的任何现有分区重叠。带IN的形式用于列表分区,带FROM和TO的形式用于范围分区,带WITH的形式用于 hash 分区。partition_bound_expr是任何无变量表达式(不允许子查询、窗口函数、聚合函数和集合返回函数)。它的数据类型必须与相应分区键列的数据类型相匹配。表达式在表创建时只计算一次,因此它甚至可以包含易失性表达式,例如。CURRENT_TIMESTAMP在创建列表分区时,可以指定
NULL,表示该分区允许分区键列为 NULL。但是,对于给定的父表,这样的列表分区不能多于一个。NULL不能用于范围分区。创建范围分区时,由
FROM指定的下界是包含边界,而由TO指定的上界是不包含边界。也就是说,FROM列表中指定的值是该分区相应分区键列的有效值,而TO列表中的值不是。请注意,必须根据按行比较的规则来理解这一点(第 9.25.5 节)。例如,给定PARTITION BY RANGE (x,y),分区边界FROM (1, 2) TO (3, 4)允许x=1且任意y>=2,x=2且任意非 NULL 的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)具有“无穷大”的概念,那只是另一种可存储的值。这不同于MINVALUE和MAXVALUE,后两者并非可存储的实际值,而只是表示值无界的方式。MAXVALUE可以视为大于任何其他值,包括“无穷大”;MINVALUE可以视为小于任何其他值,包括“负无穷大”。因此,范围FROM ('infinity') TO (MAXVALUE)并不是空范围;它只允许存储一个值 — “无穷大”。如果指定了
DEFAULT,则该表将创建为父表的默认分区。此选项不适用于 hash 分区表。任何不适合该父表其他分区的分区键值都会被路由到默认分区。当一个表已有
DEFAULT分区并且要向其添加新分区时,必须扫描默认分区,以验证其中不包含应属于新分区的任何行。如果默认分区包含大量行,这可能会很慢。如果默认分区是外部表,或者它具有可证明不可能包含应放入新分区之行的约束,则会跳过扫描。创建 hash 分区时,必须指定模数和余数。模数必须是正整数,余数必须是小于模数的非负整数。通常,在最初设置 hash 分区表时,应选择一个等于分区数的模数,并为每个分区指定相同的模数和不同的余数(见下文示例)。不过,并不要求每个分区都有相同的模数;只要求 hash 分区表中出现的每个模数都是下一个更大模数的因数。这样就可以按增量方式增加分区数量,而不必一次移动全部数据。例如,假设你有一个包含 8 个分区的 hash 分区表,每个分区的模数都是 8,但发现有必要将分区数增加到 16。你可以分离其中一个模数为 8 的分区,再创建两个新的模数为 16 的分区来覆盖同一部分键空间(其中一个的余数等于被分离分区的余数,另一个的余数等于该值加 8),然后重新向它们填充数据。之后可以对每个模数为 8 的分区重复这一过程,也许是在之后某个时间点,直到一个不剩。虽然每一步仍可能涉及大量数据移动,但仍优于创建一张全新的表并一次性移动所有数据。
分区必须具有与其所属分区表相同的列名和类型。对分区表列名或类型的修改会自动传播到所有分区。
CHECK约束会自动被每个分区继承,但单个分区也可以指定额外的CHECK约束;与父表中名称和条件相同的额外约束将与父表约束合并。可以为每个分区分别指定默认值。但是请注意,在通过分区表插入元组时不会应用分区的默认值。插入分区表中的行将自动路由到正确的分区。如果不存在合适的分区,则会发生错误。
像
TRUNCATE这样通常会影响表及其所有继承子表的操作,会级联到所有分区,但也可以在单个分区上执行。请注意,使用
PARTITION OF创建分区需要对父分区表获取ACCESS EXCLUSIVE锁。类似地,使用DROP TABLE删除分区也需要对父表获取ACCESS EXCLUSIVE锁。可以使用ALTER TABLE ATTACH/DETACH PARTITION以更弱的锁执行这些操作,从而减少对分区表并发操作的干扰。LIKEsource_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设置的更多信息,请参见第 66.2 节。INCLUDING ALLINCLUDING ALL是选择所有可用单项选项的缩写形式。(可以在INCLUDING ALL之后再写单独的EXCLUDING子句,以选中除某些特定选项之外的全部选项。)
LIKE子句也可用于从视图、外部表或复合类型复制列定义。不适用的选项(例如从视图复制INCLUDING INDEXES)会被忽略。CONSTRAINTconstraint_name列约束或表约束的可选名称。如果约束被违反,错误消息中会包含该约束名,因此诸如
col must be positive这样的约束名可以向客户端应用传达有用的约束信息。(若约束名中包含空格,则需要用双引号指定。)如果未指定约束名,系统会生成一个。NOT NULL [ NO INHERIT ]该列不允许包含空值。
标记为
NO INHERIT的约束不会传播到子表。NULL该列允许包含空值。这是默认情况。
该子句仅为兼容非标准 SQL 数据库而提供,不建议在新应用中使用。
CHECK (expression) [ NO INHERIT ]CHECK子句指定一个产生布尔结果的表达式。要使插入或更新成功,新行或更新后的行必须满足该表达式。计算结果为 TRUE 或 UNKNOWN 的表达式视为成功。如果插入或更新操作中的任何一行得到 FALSE 结果,就会抛出错误异常,并且插入或更新不会修改数据库。作为列约束指定的检查约束只应引用该列的值,而出现在表约束中的表达式可以引用多个列。当前,
CHECK表达式不能包含子查询,也不能引用当前行的列之外的变量(参见第 5.5.1 节)。可以引用系统列tableoid,但不能引用其他系统列。标记为
NO INHERIT的约束不会传播到子表。当一个表有多个
CHECK约束时,在检查完NOT NULL约束之后,会按名称的字母顺序对每一行进行检查。(9.5 之前的 PostgreSQL 版本并不保证CHECK约束的特定触发顺序。)DEFAULTdefault_exprDEFAULT子句为其所在列指定默认数据值。该值是一个不含变量的表达式(特别是,不允许引用当前表中的其他列)。子查询也不允许。默认值表达式的数据类型必须匹配列的数据类型。默认值表达式会用于任何未为该列指定值的插入操作。如果一列没有默认值,则默认值为 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_nameWITHOUT 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子句会向该索引添加一个或多个仅作为“载荷”的列:对这些列不强制唯一性,而且该索引也不能据此进行搜索。不过,它们可以通过仅索引扫描取回。注意,尽管约束不在内含列上强制执行,它仍然依赖于这些列。因此,对这类列执行某些操作(例如DROP COLUMN)可能导致约束和索引被级联删除。PRIMARY KEY(列约束)PRIMARY KEY ([column_name[, ... ] [,column_nameWITHOUT OVERLAPS ] )INCLUDE (](表约束)column_name[, ...])PRIMARY KEY约束指定表的一列或多列只能包含唯一(不重复)且非空的值。无论作为列约束还是表约束,一个表都只能指定一个主键。主键约束所引用的列集合应不同于同一表上定义的任何唯一约束所引用的列集合。(否则,该唯一约束是冗余的,会被丢弃。)
PRIMARY KEY强制的数据约束与UNIQUE和NOT NULL的组合相同。不过,将一组列标识为主键还会为模式设计提供元数据,因为主键意味着其他表可以将这组列作为行的唯一标识符来依赖。放在分区表上时,
PRIMARY KEY约束与前面描述的UNIQUE约束有相同的限制。添加
PRIMARY KEY约束会自动在约束所用的列或列组上创建唯一 B-树索引;如果指定了WITHOUT OVERLAPS,则会创建 GiST 索引。可选的
INCLUDE子句会向该索引添加一个或多个仅作为“载荷”的列:对这些列不强制唯一性,而且该索引也不能据此进行搜索。不过,它们可以通过仅索引扫描取回。注意,尽管约束不在内含列上强制执行,它仍然依赖于这些列。因此,对这类列执行某些操作(例如DROP COLUMN)可能导致约束和索引被级联删除。EXCLUDE [ USINGindex_method] (exclude_elementWITHoperator[, ... ] )index_parameters[ WHERE (predicate) ]EXCLUDE子句定义一个排他约束。它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,这些比较不会全部返回TRUE。如果所有指定操作符都测试相等,这就等价于UNIQUE约束,尽管普通唯一约束会更快。不过,排他约束可以指定比简单相等更一般的约束。例如,你可以通过使用&&操作符来指定一个约束,使表中不存在两个包含重叠圆的行(见第 8.8 节)。这些操作符必须是可交换的。排他约束通过一个与约束同名的索引来实现,因此每个指定操作符都必须与索引访问方法
index_method的适当操作符类关联(见第 11.10 节)。每个exclude_element都定义了索引的一列,因此它可以可选地指定排序规则、操作符类、操作符类参数和/或排序选项;这些在CREATE INDEX中有完整说明。访问方法必须支持
amgettuple(见第 63 章);目前这意味着不能使用 GIN。虽然允许,但在排他约束上使用 B-树或 hash 索引意义不大,因为它们做不到比普通唯一约束更好的事情。因此,实践中访问方法总是 GiST 或 SP-GiST。predicate允许你只在表的一个子集上指定排他约束;在内部,这会创建一个部分索引。注意,谓词周围的圆括号是必需的。在为多级分区层次结构建立排他约束时,目标分区表分区键中的所有列,以及其所有后代分区表分区键中的所有列,都必须包含在约束定义中。此外,这些列必须使用等值操作符进行比较。这些限制保证潜在冲突的行会落在同一分区中。约束也可以引用不属于任何分区键的其他列,这些列可以使用任何合适的操作符来比较。
REFERENCES(列约束)reftable[ (refcolumn) ] [ MATCHmatchtype] [ ON DELETEreferential_action] [ ON UPDATEreferential_action]FOREIGN KEY ((表约束)column_name[, ... ] [, PERIODcolumn_name] ) REFERENCESreftable[ (refcolumn[, ... ] [, PERIODrefcolumn] ) ] [ MATCHmatchtype] [ ON DELETEreferential_action] [ ON UPDATEreferential_action]这些子句指定外键约束,要求新表的一列或多列组成的一组只能包含与被引用表某一行的被引用列中值相匹配的值。若省略
refcolumn列表,则使用reftable的主键。否则,refcolumn列表必须引用某个不可延迟的唯一约束或主键约束的列,或者引用某个非部分唯一索引的列。如果最后一列标记为
PERIOD,则会按特殊方式处理。非PERIOD列按相等性比较(并且至少需要一列),而PERIOD列则不会。取而代之的是,只有当被引用表中基于键的非PERIOD部分相匹配的记录,其合并后的PERIOD值能够完整覆盖引用记录的 PERIOD 值时,约束才算满足。换言之,该引用在其整个持续区间内都必须有对应的被引用对象。该列必须是范围类型或多范围类型。此外,被引用表必须具有用WITHOUT OVERLAPS声明的主键或唯一约束。最后,如果外键包含 PERIODcolumn_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约束。USINGmethod该可选子句指定存储新表内容所用的表访问方法;该方法必须是类型为
TABLE的访问方法。详见第 62 章。如果未指定此选项,则会为新表选择默认表访问方法。详见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控制临时表在事务块结束时的行为。三种选项如下:PRESERVE ROWS在事务结束时不执行任何特殊操作。这是默认行为。
DELETE ROWS在每个事务块结束时删除临时表中的所有行。本质上,相当于在每次提交时自动执行一次
TRUNCATE。用于分区表时,此操作不会级联到其分区。DROP在当前事务块结束时删除临时表。用于分区表时,此操作会删除其分区;用于带有继承子表的表时,则会删除其依赖子表。
TABLESPACEtablespace_nametablespace_name是新表要创建于其中的表空间名称。若未指定,则参考default_tablespace;如果该表是临时表,则参考temp_tablespaces。对于分区表,由于表本身不需要存储,所指定的表空间会覆盖default_tablespace,成为在未显式指定其他表空间时新建分区所使用的默认表空间。USING INDEX TABLESPACEtablespace_name该子句允许选择与
UNIQUE、PRIMARY KEY或EXCLUDE约束相关联的索引要创建在哪个表空间中。若未指定,则参考default_tablespace;如果该表是临时表,则参考temp_tablespaces。
存储参数
WITH 子句可以为表以及与 UNIQUE、PRIMARY KEY 或 EXCLUDE 约束关联的索引指定存储参数。索引的存储参数已在CREATE INDEX中介绍。当前可用于表的存储参数列在下文。对于其中许多参数,如下所示,还存在一个同名且带 toast. 前缀的附加参数,用于控制该表的二级 TOAST 表(如果有)的行为(更多有关 TOAST 的信息见第 66.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)为特定表启用或禁用自动清理守护进程。如果为真,自动清理守护进程将按照第 24.1.6 节中讨论的规则,在该表上执行自动
VACUUM和/或ANALYZE操作。如果为假,则该表不会被自动清理,但为了防止事务 ID 回卷,仍可能对其执行自动清理。有关回卷防护的更多信息,见第 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_truncate参数的每表取值。若
VACUUM指定了TRUNCATE参数,将覆盖此选项的值。autovacuum_vacuum_threshold,toast.autovacuum_vacuum_threshold(integer)autovacuum_vacuum_threshold参数的每表取值。
autovacuum_vacuum_max_threshold,toast.autovacuum_vacuum_max_threshold(integer)autovacuum_vacuum_max_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)log_autovacuum_min_duration,toast.log_autovacuum_min_duration(integer)log_autovacuum_min_duration参数的每表取值。
vacuum_max_eager_freeze_failure_rate,toast.vacuum_max_eager_freeze_failure_rate(floating point)user_catalog_table(boolean)将该表声明为逻辑复制用途的附加目录表。详见第 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));
创建 hash 分区表:
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);
创建 hash 分区表的分区:
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 的扩展。
另见
语法演化
相邻大版本之间的差异,新的在前。版本号链接到对应快照。
PostgreSQL 20← 19正文更新
正文更新PostgreSQL 19← 18语法变化
+ CREATE [ persistence_mode ] TABLE [ IF NOT EXISTS ] table_name ( [+ { column_name data_type [ column_storage ] [ column_compression ] [ COLLATE collation ] [ column_constraint [ ... ] ]+ CREATE [ persistence_mode ] TABLE [ IF NOT EXISTS ] table_name+ CREATE [ persistence_mode ] TABLE [ IF NOT EXISTS ] table_name+ { [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } } | UNLOGGED+ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT }+ COMPRESSION compression_method− 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 [ ... ] ]− CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name− CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name正文更新PostgreSQL 18← 17语法变化
+ { NOT NULL [ NO INHERIT ] |+ GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] |+ [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]+ [ 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 |+ FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ]+ [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]正文更新PostgreSQL 17← 16正文更新
正文更新PostgreSQL 16← 15语法变化
+ { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ]正文更新PostgreSQL 15← 14语法变化
+ UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters |+ UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters |+ { NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }正文更新PostgreSQL 14← 13语法变化
+ { column_name data_type [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ]+ { INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }正文更新PostgreSQL 13← 12语法变化
+ { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]正文更新PostgreSQL 12← 11语法变化
+ [ USING method ]+ [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]+ [ USING method ]+ [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]+ [ USING method ]+ [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]+ GENERATED ALWAYS AS ( generation_expr ) STORED |+ GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |+ [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }+ [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }+ { INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }+ IN ( partition_bound_expr [, ...] ) |+ FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )+ TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |− [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]− [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]− [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]− [ ON DELETE action ] [ ON UPDATE action ] }− [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] }− IN ( { numeric_literal | string_literal | TRUE | FALSE | NULL } [, ...] ) |− FROM ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] )− TO ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] ) |正文更新PostgreSQL 11← 10语法变化
+ [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]+ [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]+ ) ] { FOR VALUES partition_bound_spec | DEFAULT }+ [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]+ TO ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] ) |+ WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )+ [ INCLUDE ( column_name [, ... ] ) ]正文更新
同组命令
| 命令 | 动词 | 对象 | 版本变动 | 最近变更 |
|---|---|---|---|---|
TRUNCATE | TRUNCATE | — | — | |
| 清空一个表或一组表 | 现存 | |||
CREATE MATERIALIZED VIEW | CREATE | MATERIALIZED VIEW | 121 次 | |
| 定义一个新物化视图 | 现存 | |||
ALTER MATERIALIZED VIEW | ALTER | MATERIALIZED VIEW | 164 次 | |
| 更改一个物化视图的定义 | 现存 | |||
DROP MATERIALIZED VIEW | DROP | MATERIALIZED VIEW | — | |
| 移除一个物化视图 | 现存 | |||
REFRESH MATERIALIZED VIEW | REFRESH | MATERIALIZED VIEW | — | |
| 替换物化视图的内容 | 现存 | |||
CREATE SEQUENCE | CREATE | SEQUENCE | 182 次 | |
| 定义一个新的序列发生器 | 现存 | |||
ALTER SEQUENCE | ALTER | SEQUENCE | 183 次 | |
| 更改序列发生器的定义 | 现存 | |||
DROP SEQUENCE | DROP | SEQUENCE | — | |
| 移除一个序列 | 现存 | |||
CREATE TABLE | CREATE | TABLE | 198 次 | |
| 定义一个新表 | 现存 | |||
ALTER TABLE | ALTER | TABLE | 188 次 | |
| 更改一个表的定义 | 现存 | |||
DROP TABLE | DROP | TABLE | — | |
| 移除一个表 | 现存 | |||
CREATE TABLE AS | CREATE | TABLE AS | 192 次 | |
| 根据查询结果定义一个新表 | 现存 | |||
CREATE VIEW | CREATE | VIEW | — | |
| 定义一个新视图 | 现存 | |||
ALTER VIEW | ALTER | VIEW | 142 次 | |
| 更改视图的定义 | 现存 | |||
DROP VIEW | DROP | VIEW | — | |
| 移除一个视图 | 现存 | |||