CREATE TABLE — 定义一个新表
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ]table_name
( [ {column_name
data_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_name
OFtype_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_name
PARTITION 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
] wherecolumn_constraint
is: [ CONSTRAINTconstraint_name
] { NOT NULL | NULL | CHECK (expression
) [ NO INHERIT ] | DEFAULTdefault_expr
| GENERATED ALWAYS AS (generation_expr
) STORED | 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 ] andtable_constraint
is: [ CONSTRAINTconstraint_name
] { CHECK (expression
) [ NO INHERIT ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] (column_name
[, ... ] )index_parameters
| PRIMARY KEY (column_name
[, ... ] )index_parameters
| EXCLUDE [ USINGindex_method
] (exclude_element
WITHoperator
[, ... ] )index_parameters
[ WHERE (predicate
) ] | FOREIGN KEY (column_name
[, ... ] ) REFERENCESreftable
[ (refcolumn
[, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action
] [ ON UPDATEreferential_action
] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] andlike_option
is: { INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL } andpartition_bound_spec
is: IN (partition_bound_expr
[, ...] ) | FROM ( {partition_bound_expr
| MINVALUE | MAXVALUE } [, ...] ) TO ( {partition_bound_expr
| MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUSnumeric_literal
, REMAINDERnumeric_literal
)index_parameters
inUNIQUE
,PRIMARY KEY
, andEXCLUDE
constraints are: [ INCLUDE (column_name
[, ... ] ) ] [ WITH (storage_parameter
[=value
] [, ... ] ) ] [ USING INDEX TABLESPACEtablespace_name
]exclude_element
in anEXCLUDE
constraint is: {column_name
| (expression
) } [ COLLATEcollation
] [opclass
[ (opclass_parameter
=value
[, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]referential_action
in aFOREIGN 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
或 TEMP
#如果指定,则该表将创建为临时表。临时表会在会话结束时自动删除,或者可以选择在当前事务结束时删除(请参见下面的 ON COMMIT
)。默认的 search_path 首先包含临时模式,因此在临时表存在期间,除非使用模式限定名称引用,否则不会为新计划选择同名的现有永久表。在临时表上创建的任何索引也将自动是临时的。
自动清理守护进程无法访问,因此无法清理或分析临时表。因此,应通过会话 SQL 命令执行适当的清理和分析操作。例如,如果临时表将在复杂的查询中使用,那么在填充临时表后,最好在临时表上运行 ANALYZE
。
可选地,可以在 TEMPORARY
或 TEMP
之前写入 GLOBAL
或 LOCAL
。这目前在 PostgreSQL 中没有任何区别,并且已被弃用;请参见下面的 兼容性。
UNLOGGED
#如果指定,则该表将创建为未记录的表。写入未记录表的数据不会写入预写式日志(请参见第 28 章),这使得它们比普通表快得多。但是,它们不是崩溃安全的:未记录的表会在崩溃或不干净的关闭后自动截断。未记录表的内容也不会复制到备用服务器。在未记录表上创建的任何索引也将自动是未记录的。
如果指定此项,则与未记录表一起创建的任何序列(用于标识或序列列)也将创建为未记录的。
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
会将存储模式设置为列数据类型的默认模式。EXTENDED
是大多数支持非 PLAIN
存储的数据类型的默认值。使用 EXTERNAL
将使对非常大的 text
和 bytea
值进行子字符串操作的速度更快,但会增加存储空间。有关更多信息,请参见 第 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 时更改),但对于列表分区,分区键必须包含单个列或表达式。
范围和列表分区需要 B 树运算符类,而哈希分区需要哈希运算符类。如果未显式指定运算符类,则将使用相应类型的默认运算符类;如果不存在默认运算符类,则会引发错误。当使用哈希分区时,所使用的运算符类必须实现支持函数 2(有关详细信息,请参阅第 36.16.3 节)。
分区表被划分为子表(称为分区),这些子表是使用单独的 CREATE TABLE
命令创建的。分区表本身是空的。插入到表中的数据行会根据分区键中列或表达式的值路由到分区。如果没有与新行中的值匹配的现有分区,将报告错误。
分区表不支持 EXCLUDE
约束;但是,您可以在各个分区上定义这些约束。
有关表分区的更多讨论,请参阅第 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
列表中的值则不是。请注意,此语句必须根据逐行比较的规则来理解(第 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
)具有“无穷大”的概念,这只是可以存储的另一个值。这与 MINVALUE
和 MAXVALUE
不同,后者不是可以存储的实际值,而是表示值无界的方式。MAXVALUE
可以被认为大于任何其他值,包括“无穷大”,而 MINVALUE
可以被认为小于任何其他值,包括“负无穷大”。因此,范围 FROM ('infinity') TO (MAXVALUE)
不是空范围;它允许精确地存储一个值 — “无穷大”。
如果指定了 DEFAULT
,则该表将创建为父表的默认分区。此选项不适用于哈希分区表。不适合给定父表的任何其他分区中的分区键值将被路由到默认分区。
当表具有现有的 DEFAULT
分区并且向其中添加新分区时,必须扫描默认分区以验证它是否不包含任何应正确放入新分区中的行。如果默认分区包含大量行,则此操作可能会很慢。如果默认分区是外部表,或者它具有约束证明它不能包含应放置在新分区中的行,则将跳过扫描。
创建哈希分区时,必须指定模数和余数。模数必须是正整数,余数必须是小于模数的非负整数。通常,在初始设置哈希分区表时,应选择等于分区数的模数,并为每个表分配相同的模数和不同的余数(请参阅下面的示例)。但是,并非要求每个分区都具有相同的模数,而仅要求哈希分区表的各个分区中出现的每个模数都是下一个较大模数的因子。这允许在不需要一次移动所有数据的情况下逐步增加分区数。例如,假设您有一个具有 8 个分区的哈希分区表,每个分区都有模数 8,但发现有必要将分区数增加到 16。您可以分离一个模数为 8 的分区,创建两个新的模数为 16 的分区,覆盖键空间的相同部分(一个余数等于分离分区的余数,另一个余数等于该值加 8),然后用数据重新填充它们。然后,您可以对每个模数为 8 的分区重复此操作(可能在稍后的时间),直到没有剩余的分区为止。虽然这可能仍然涉及每个步骤的大量数据移动,但这仍然比必须创建一个全新的表并一次移动所有数据要好得多。
分区必须具有与其所属的分区表相同的列名和类型。对分区表的列名或类型的修改将自动传播到所有分区。CHECK
约束将自动被每个分区继承,但单个分区可以指定额外的 CHECK
约束;与父约束具有相同名称和条件的附加约束将与父约束合并。可以为每个分区单独指定默认值。但是请注意,通过分区表插入元组时,不会应用分区的默认值。
插入到分区表中的行将自动路由到正确的分区。如果不存在合适的分区,则会发生错误。
诸如 TRUNCATE
之类的操作通常会影响表及其所有继承的子项,这些操作将级联到所有分区,但也可以在单个分区上执行。
请注意,使用 PARTITION OF
创建分区需要在父分区表上获取 ACCESS EXCLUSIVE
锁。同样,使用 DROP TABLE
删除分区需要在父表上获取 ACCESS EXCLUSIVE
锁。可以使用ALTER TABLE ATTACH/DETACH PARTITION
以较弱的锁来执行这些操作,从而减少对分区表上并发操作的干扰。
LIKE source_table
[ like_option
... ]
#LIKE
子句指定一个表,新表会自动复制该表的所有列名、数据类型以及非空约束。
与 INHERITS
不同,新表和原始表在创建完成后是完全分离的。对原始表的更改不会应用到新表,并且不可能将新表的数据包含在原始表的扫描中。
同样与 INHERITS
不同,通过 LIKE
复制的列和约束不会与类似名称的列和约束合并。如果显式指定或在另一个 LIKE
子句中指定了相同的名称,则会发出错误信号。
可选的 like_option
子句指定要复制的原始表的哪些其他属性。指定 INCLUDING
会复制该属性,指定 EXCLUDING
会忽略该属性。EXCLUDING
是默认值。如果对同一类型的对象进行了多次规范,则使用最后一个规范。可用的选项包括:
INCLUDING COMMENTS
#将复制复制的列、约束和索引的注释。默认行为是排除注释,导致新表中的复制列和约束没有注释。
INCLUDING COMPRESSION
#将复制列的压缩方法。默认行为是排除压缩方法,导致列具有默认的压缩方法。
INCLUDING CONSTRAINTS
#CHECK
约束将被复制。列约束和表约束之间没有区别。非空约束始终复制到新表。
INCLUDING DEFAULTS
#将复制复制的列定义的默认表达式。否则,不会复制默认表达式,导致新表中的复制列具有空默认值。请注意,复制调用数据库修改函数(如 nextval
)的默认值可能会在原始表和新表之间创建功能链接。
INCLUDING GENERATED
#将复制复制的列定义的任何生成表达式。默认情况下,新列将是常规基础列。
INCLUDING IDENTITY
#将复制复制的列定义的任何标识规范。为新表的每个标识列创建一个新的序列,与旧表关联的序列分开。
INCLUDING INDEXES
#将在新表上创建原始表上的索引、PRIMARY KEY
、UNIQUE
和 EXCLUDE
约束。新索引和约束的名称根据默认规则选择,无论原始名称如何。(此行为避免了新索引可能出现的重复名称故障。)
INCLUDING STATISTICS
#扩展统计信息将复制到新表。
INCLUDING STORAGE
#将复制复制的列定义的 STORAGE
设置。默认行为是排除 STORAGE
设置,导致新表中的复制列具有特定于类型的默认设置。有关 STORAGE
设置的更多信息,请参见 第 65.2 节。
INCLUDING ALL
#INCLUDING ALL
是一种简写形式,用于选择所有可用的单个选项。(在 INCLUDING ALL
之后编写单独的 EXCLUDING
子句来选择除某些特定选项之外的所有选项可能很有用。)
LIKE
子句还可以用于从视图、外部表或复合类型复制列定义。将忽略不适用的选项(例如,视图中的 INCLUDING INDEXES
)。
CONSTRAINT constraint_name
#列或表约束的可选名称。如果违反约束,则错误消息中会显示约束名称,因此可以使用诸如 col must be positive
之类的约束名称向客户端应用程序传达有用的约束信息。(需要使用双引号来指定包含空格的约束名称。)如果未指定约束名称,则系统会生成一个名称。
NOT NULL
#该列不允许包含空值。
NULL
#该列允许包含空值。这是默认值。
提供此子句仅为了与非标准 SQL 数据库兼容。不鼓励在新应用程序中使用它。
CHECK ( expression
) [ NO INHERIT ]
#CHECK
子句指定一个表达式,该表达式产生一个布尔结果,新行或更新行必须满足该结果,才能成功进行插入或更新操作。计算结果为 TRUE 或 UNKNOWN 的表达式成功。如果插入或更新操作的任何行产生 FALSE 结果,则会引发错误异常,并且插入或更新不会更改数据库。作为列约束指定的检查约束应仅引用该列的值,而出现在表约束中的表达式可以引用多列。
当前,CHECK
表达式不能包含子查询,也不能引用当前行中的列以外的变量(请参见第 5.5.1 节)。可以引用系统列 tableoid
,但不能引用任何其他系统列。
标记有 NO INHERIT
的约束不会传播到子表。
当表具有多个 CHECK
约束时,将在检查 NOT NULL
约束之后,按名称的字母顺序对每个行进行测试。(9.5 之前的 PostgreSQL 版本不遵守 CHECK
约束的任何特定触发顺序。)
DEFAULT default_expr
#DEFAULT
子句为列定义中出现的列分配一个默认数据值。该值是任何无变量的表达式(特别是,不允许交叉引用当前表中的其他列)。也不允许子查询。默认表达式的数据类型必须与列的数据类型匹配。
默认表达式将用于任何未指定列值的插入操作。如果列没有默认值,则默认值为 null。
GENERATED ALWAYS AS ( generation_expr
) STORED
#此子句将列创建为生成列。该列不能写入,读取时将返回指定表达式的结果。
需要关键字 STORED
来表示该列将在写入时计算并存储在磁盘上。
生成表达式可以引用表中的其他列,但不能引用其他生成列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。
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
、name
LOGGED
和 UNLOGGED
,它们允许选择序列的名称和持久性级别。如果没有 SEQUENCE NAME
,系统会为序列选择一个未使用的名称。如果没有 LOGGED
或 UNLOGGED
,则序列将具有与表相同的持久性级别。
UNIQUE [ NULLS [ NOT ] DISTINCT ]
(列约束)UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name
[, ... ] )
[ INCLUDE ( column_name
[, ...])
] (表约束) #UNIQUE
约束指定表的多个列可以仅包含唯一值。唯一表约束的行为与唯一列约束相同,但增加了跨多列的能力。因此,该约束强制任何两行在这些列的至少一列中必须不同。
出于唯一约束的目的,除非指定了 NULLS NOT DISTINCT
,否则空值不被视为相等。
每个唯一约束应命名一组列,该组列与为表定义的任何其他唯一约束或主键约束命名的列集不同。(否则,将丢弃冗余的唯一约束。)
在为多级分区层次结构建立唯一约束时,目标分区表的所有分区键列以及其所有后代分区表的列都必须包含在约束定义中。
添加唯一约束会自动在约束中使用的列或列组上创建唯一的 btree 索引。创建的索引与唯一约束同名。
可选的 INCLUDE
子句向该索引添加一个或多个仅作为“负载”的列:不会对它们强制执行唯一性,并且不能基于这些列搜索索引。但是,它们可以通过仅索引扫描来检索。请注意,尽管不强制对包含的列执行约束,但它仍然依赖于它们。因此,对此类列的某些操作(例如,DROP COLUMN
)可能会导致级联的约束和索引删除。
PRIMARY KEY
(列约束)PRIMARY KEY ( column_name
[, ... ] )
[ INCLUDE ( column_name
[, ...])
] (表约束) #PRIMARY KEY
约束指定表中的一个或多个列只能包含唯一(非重复)的非空值。对于一个表,只能指定一个主键,无论是作为列约束还是表约束。
主键约束应命名一组与为同一表定义的任何唯一约束命名的列不同的列。(否则,唯一约束是多余的,将被丢弃。)
PRIMARY KEY
强制执行与 UNIQUE
和 NOT NULL
的组合相同的数据约束。但是,将一组列标识为主键还提供了有关架构设计的元数据,因为主键意味着其他表可以依赖这组列作为行的唯一标识符。
当放置在分区表上时,PRIMARY KEY
约束共享先前为 UNIQUE
约束描述的限制。
添加 PRIMARY KEY
约束会自动在约束中使用的列或列组上创建唯一的 btree 索引。该索引与主键约束同名。
可选的 INCLUDE
子句向该索引添加一个或多个仅作为“负载”的列:不会对它们强制执行唯一性,并且不能基于这些列搜索索引。但是,它们可以通过仅索引扫描来检索。请注意,尽管不强制对包含的列执行约束,但它仍然依赖于它们。因此,对此类列的某些操作(例如,DROP COLUMN
)可能会导致级联的约束和索引删除。
EXCLUDE [ USING index_method
] ( exclude_element
WITH operator
[, ... ] ) index_parameters
[ WHERE ( predicate
) ]
#EXCLUDE
子句定义了一个排除约束,该约束保证如果使用指定的运算符在指定的列或表达式上比较任何两行,则并非所有这些比较都会返回 TRUE
。如果所有指定的运算符都测试相等性,则这等效于 UNIQUE
约束,尽管普通的唯一约束会更快。但是,排除约束可以指定比简单相等性更通用的约束。例如,您可以使用 &&
运算符指定表中没有两行包含重叠的圆(请参阅第 8.8 节)。运算符必须是可交换的。
排除约束是使用与约束同名的索引实现的,因此每个指定的运算符都必须与索引访问方法 index_method
的适当运算符类相关联(请参阅第 11.10 节)。每个 exclude_element
定义索引的一列,因此它可以选择指定排序规则、运算符类、运算符类参数和/或排序选项;这些在CREATE INDEX 中进行了完整描述。
访问方法必须支持 amgettuple
(请参阅第 62 章);目前这意味着GIN不能使用。尽管允许使用,但在排除约束中使用 B 树或哈希索引几乎没有意义,因为这并没有比普通的唯一约束做得更好。因此,在实践中,访问方法将始终是GiST或SP-GiST.
predicate
允许您在表的子集上指定排除约束;在内部,这将创建一个部分索引。请注意,谓词必须用括号括起来。
REFERENCES reftable
[ ( refcolumn
) ] [ MATCH matchtype
] [ ON DELETE referential_action
] [ ON UPDATE referential_action
]
(列约束)FOREIGN KEY ( column_name
[, ... ] ) REFERENCES reftable
[ ( refcolumn
[, ... ] ) ] [ MATCH matchtype
] [ ON DELETE referential_action
] [ ON UPDATE referential_action
]
(表约束) #这些子句指定一个外键约束,该约束要求新表的一个或多个列的组只能包含与引用的表中某行的引用列中的值匹配的值。如果省略 refcolumn
列表,则使用 reftable
的主键。否则,refcolumn
列表必须引用不可延迟的唯一或主键约束的列,或者是非部分唯一索引的列。用户必须对引用的表(整个表或特定的引用列)具有 REFERENCES
权限。添加外键约束需要对引用的表进行 SHARE ROW EXCLUSIVE
锁定。请注意,不能在临时表和永久表之间定义外键约束。
使用给定的匹配类型,将插入到引用列中的值与引用表和引用列的值进行匹配。有三种匹配类型:MATCH FULL
、MATCH 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
操作指定列的子集。(如果默认值不为空,则引用的表中必须有一行与默认值匹配,否则操作将失败。)
如果引用的列经常更改,则明智的做法是在引用列中添加索引,以便可以更有效地执行与外键约束关联的引用操作。
DEFERRABLE
NOT DEFERRABLE
#这控制约束是否可以延迟。不可延迟的约束将在每个命令之后立即检查。可延迟的约束的检查可以推迟到事务结束时(使用 SET CONSTRAINTS
命令)。NOT DEFERRABLE
是默认值。目前,只有 UNIQUE
、PRIMARY KEY
、EXCLUDE
和 REFERENCES
(外键)约束接受此子句。NOT NULL
和 CHECK
约束不可延迟。请注意,可延迟的约束不能用作 INSERT
语句中包含 ON CONFLICT DO UPDATE
子句的冲突仲裁器。
INITIALLY IMMEDIATE
INITIALLY DEFERRED
#如果约束是可延迟的,则此子句指定检查约束的默认时间。如果约束是 INITIALLY IMMEDIATE
,则在每个语句之后都会检查它。这是默认值。如果约束是 INITIALLY DEFERRED
,则仅在事务结束时检查它。约束检查时间可以使用 SET CONSTRAINTS
命令进行更改。
USING method
#这个可选的子句指定用于存储新表内容的表访问方法;该方法需要是 TABLE
类型的访问方法。有关详细信息,请参阅第 61 章。如果未指定此选项,则为新表选择默认表访问方法。有关详细信息,请参阅default_table_access_method。
创建分区时,如果设置了表访问方法,则表访问方法是其分区表的访问方法。
WITH ( storage_parameter
[= value
] [, ... ] )
#此子句为表或索引指定可选的存储参数;有关详细信息,请参见下面的存储参数。为了向后兼容,表的 WITH
子句还可以包含 OIDS=FALSE
,以指定新表的行不应包含 OID(对象标识符),OIDS=TRUE
不再支持。
WITHOUT OIDS
#这是用于声明不使用 OID 的表的向后兼容语法,不再支持创建使用 OID 的表。
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 的更多信息,请参见第 65.2 节)。如果设置了表参数值,而没有设置等效的 toast.
参数,则 TOAST 表将使用表的参数值。不支持为分区表指定这些参数,但是可以为各个叶子分区指定它们。
fillfactor
(integer
) #表的填充因子是 10 到 100 之间的百分比。100(完全打包)是默认值。当指定较小的填充因子时,INSERT
操作仅将表页打包到指示的百分比;每个页面上的剩余空间保留用于更新该页面上的行。这使得 UPDATE
有机会将行的更新副本放在与原始行相同的页面上,这比将其放在不同的页面上更有效,并且使仅堆元组更新更有可能。对于条目永远不会更新的表,完全打包是最佳选择,但是在频繁更新的表中,较小的填充因子是合适的。无法为 TOAST 表设置此参数。
toast_tuple_target
(integer
) #toast_tuple_target 指定在尝试将长列值压缩和/或移动到 TOAST 表之前所需的最小元组长度,并且也是一旦开始 toasting 后,我们尝试将长度减少到的目标长度。这会影响标记为 External(用于移动)、Main(用于压缩)或 Extended(用于两者)的列,并且仅适用于新元组。对现有行没有影响。默认情况下,此参数设置为允许每个块至少 4 个元组,在默认块大小下,这将是 2040 字节。有效值介于 128 字节和(块大小 - 标头)之间,默认为 8160 字节。对于非常短或非常长的行,更改此值可能没有用。请注意,默认设置通常接近最佳,并且在某些情况下,设置此参数可能会产生负面影响。无法为 TOAST 表设置此参数。
parallel_workers
(integer
) #这设置了应用于辅助此表的并行扫描的工作进程数。如果未设置,系统将根据关系大小确定一个值。计划器或使用并行扫描的实用程序语句选择的实际工作进程数可能更少,例如,由于 max_worker_processes 的设置。
autovacuum_enabled
, toast.autovacuum_enabled
(boolean
) #为特定表启用或禁用自动清理守护进程。如果为 true,则自动清理守护进程将按照第 24.1.6 节中讨论的规则,在此表上执行自动 VACUUM
和/或 ANALYZE
操作。如果为 false,则此表将不会自动清理,除非是为了防止事务 ID 回绕。有关回绕预防的更多信息,请参见第 24.1.5 节。请注意,如果 autovacuum 参数为 false,则自动清理守护进程根本不运行(除非是为了防止事务 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
和自动清理会执行截断,并且截断的页面的磁盘空间将返回给操作系统。请注意,截断需要对表使用 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_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_min_age
参数大于系统范围的 autovacuum_freeze_max_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_min_age
参数大于系统范围的 autovacuum_multixact_freeze_max_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
) #将该表声明为逻辑复制的其他目录表。有关详细信息,请参见第 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
。ON COMMIT DROP
选项在 SQL 中不存在。
当 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
约束)来说,这种额外的自由是不存在的,因为关联的索引与约束同名,并且索引名称在同一模式的所有关系中必须是唯一的。
目前,PostgreSQL 完全不记录非空约束的名称,因此它们不受唯一性限制。这在未来的版本中可能会更改。
通过 INHERITS
子句实现的多重继承是 PostgreSQL 语言扩展。SQL:1999 及更高版本使用不同的语法和不同的语义定义了单继承。PostgreSQL 尚未支持 SQL:1999 风格的继承。
PostgreSQL 允许创建没有列的表(例如,CREATE TABLE foo();
)。这是 SQL 标准的扩展,该标准不允许零列表。零列表本身并不是很有用,但是禁止它们会在 ALTER TABLE DROP COLUMN
中创建奇怪的特殊情况,因此忽略此规范限制似乎更简洁。
PostgreSQL 允许一个表拥有多个标识列。标准规定一个表最多只能有一个标识列。放宽此限制主要是为了在进行模式更改或迁移时提供更大的灵活性。请注意,INSERT
命令仅支持一个应用于整个语句的覆盖子句,因此不支持具有不同行为的多个标识列。
选项 STORED
不是标准,但也为其他 SQL 实现所使用。SQL 标准没有指定生成列的存储。
LIKE
子句虽然 SQL 标准中存在 LIKE
子句,但 PostgreSQL 接受的许多选项都不是标准中的,并且 PostgreSQL 也未实现标准中的某些选项。
WITH
子句WITH
子句是一个 PostgreSQL 扩展;存储参数不在标准中。
PostgreSQL 的表空间概念不是标准的一部分。因此,子句 TABLESPACE
和 USING INDEX TABLESPACE
是扩展。
类型化表实现了 SQL 标准的一个子集。根据标准,类型化表具有与基础复合类型对应的列以及另一个作为“自引用列”的列。PostgreSQL 不显式支持自引用列。
PARTITION BY
子句PARTITION BY
子句是 PostgreSQL 扩展。
PARTITION OF
子句PARTITION OF
子句是 PostgreSQL 扩展。
如果您发现文档中有任何不正确、与您对特定功能的体验不符或需要进一步澄清的地方,请使用此表格报告文档问题。