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
。(lz4
仅在构建PostgreSQL时使用了--with-lz4
时才可用。)此外,compression_method
可以为default
,以显式指定默认行为,即在数据插入时查询default_toast_compression设置以确定要使用的方法。
INHERITS ( parent_table
[, ... ] )
#可选的INHERITS
子句指定一个表列表,新表将自动从此列表中继承所有列。父表可以是普通表或外部表。
使用 INHERITS
创建了一个新的子表与其父表(或父表)之间的持久关系。父表(或父表)的模式修改通常也会传播到子表,并且默认情况下,子表的数据包含在父表(或父表)的扫描中。
如果多个父表中存在相同的列名,则会报告错误,除非这些列的数据类型在每个父表中都匹配。如果没有冲突,则合并重复的列以在新表中形成单个列。如果新表的列名列表包含一个也继承的列名,则该数据类型也必须与继承的列(或列)匹配,并且列定义将合并为一个。如果新表为该列显式指定了默认值,则此默认值将覆盖从继承的列声明中获取的任何默认值。否则,所有指定该列默认值的父表都必须指定相同的默认值,否则将报告错误。
CHECK
约束的合并方式与列基本相同:如果多个父表和/或新表定义包含同名的 CHECK
约束,则这些约束都必须具有相同的检查表达式,否则将报告错误。具有相同名称和表达式的约束将合并为一个副本。在父表中标记为 NO INHERIT
的约束将不会被考虑。请注意,新表中未命名的 CHECK
约束永远不会被合并,因为始终会为其选择一个唯一的名称。
列的 STORAGE
设置也会从父表复制。
如果父表中的列是标识列,则该属性不会被继承。如果需要,可以在子表中将列声明为标识列。
PARTITION BY { RANGE | LIST | HASH } ( { column_name
| ( expression
) } [ opclass
] [, ...] )
#可选的 PARTITION BY
子句指定了表分区策略。这样创建的表称为 分区表。列或表达式的括号列表构成了表的 分区键。在使用范围或哈希分区时,分区键可以包含多个列或表达式(最多 32 个,但在构建 PostgreSQL 时可以更改此限制),但对于列表分区,分区键必须由单个列或表达式组成。
范围和列表分区需要一个 btree 运算符类,而哈希分区需要一个哈希运算符类。如果未显式指定运算符类,则将使用相应类型的默认运算符类;如果不存在默认运算符类,则会引发错误。使用哈希分区时,使用的运算符类必须实现支持函数 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。但是,对于给定的父表,此类列表分区不能超过一个。对于范围分区,不能指定 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
不同,MINVALUE
和 MAXVALUE
不是可以存储的真实值,而是表示值不受限的方式。MAXVALUE
可以认为大于任何其他值,包括“无穷大”,而 MINVALUE
可以认为小于任何其他值,包括“负无穷大”。因此,范围 FROM ('infinity') TO (MAXVALUE)
不是空范围;它只允许存储一个值——“无穷大”。
如果指定了 DEFAULT
,则该表将被创建为父表的默认分区。此选项不适用于哈希分区表。不适合给定父表的任何其他分区的分区键值将被路由到默认分区。
当表具有现有的 DEFAULT
分区并且向其添加了新分区时,必须扫描默认分区以验证它是否不包含任何应正确属于新分区中的行。如果默认分区包含大量行,这可能会很慢。如果默认分区是外部表或具有证明其不能包含应放置在新分区中的行的约束,则将跳过扫描。
创建哈希分区时,必须指定模数和余数。模数必须是正整数,余数必须是非负整数且小于模数。通常,在最初设置哈希分区表时,应选择一个等于分区数的模数,并为每个表分配相同的模数和不同的余数(请参见下面的示例)。但是,并非每个分区都必须具有相同的模数,只需要哈希分区表的分区中出现的每个模数都是下一个较大模数的因数即可。这允许在不一次移动所有数据的情况下逐步增加分区数。例如,假设您有一个具有 8 个分区的哈希分区表,每个分区都具有模数 8,但发现需要将分区数增加到 16。您可以分离一个模数为 8 的分区,创建两个新的模数为 16 的分区,覆盖键空间的相同部分(一个余数等于分离的分区的余数,另一个余数等于该值加上 8),并使用数据重新填充它们。然后,您可以重复此操作(也许在稍后的时间)以用于每个模数为 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
约束之后。(PostgreSQL 9.5之前的版本没有遵守CHECK
约束的任何特定触发顺序。)
DEFAULT default_expr
#DEFAULT
子句为包含其列定义的列分配一个默认数据值。该值是任何无变量的表达式(特别是,不允许交叉引用当前表中的其他列)。子查询也不允许。默认表达式的类型必须与列的类型匹配。
在任何不为列指定值的插入操作中都将使用默认表达式。如果列没有默认值,则默认为空。
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 ]
(column constraint)UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name
[, ... ] )
[ INCLUDE ( column_name
[, ...])
] (table constraint) #UNIQUE
约束指定表的1个或多个列组只能包含唯一值。唯一表约束的行为与唯一列约束的行为相同,但具有跨多个列的功能。因此,约束强制执行任何两行必须至少在一列上有所不同。
为了实现唯一约束,空值不被视为相等,除非指定了NULLS NOT DISTINCT
。
每个唯一约束都应该命名一组与表上定义的任何其他唯一或主键约束命名的列集不同的列集。(否则,冗余的唯一约束将被丢弃。)
在为多级分区层次结构建立唯一约束时,目标分区表的 partition key 中的所有列以及其所有后代分区表中的所有列都必须包含在约束定义中。
添加唯一约束会自动在约束中使用的列或列组上创建一个唯一的 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
不允许多列外键的一列为 null,除非所有外键列都为 null;如果它们都为 null,则不需要该行在引用表中具有匹配项。MATCH SIMPLE
允许任何外键列为 null;如果它们中的任何一个为 null,则不需要该行在引用表中具有匹配项。MATCH PARTIAL
尚未实现。(当然,可以将NOT NULL
约束应用于引用列以防止这些情况发生。)
此外,当引用列中的数据发生更改时,会在该表列的数据上执行某些操作。ON DELETE
子句指定在删除引用表中的引用行时要执行的操作。同样,ON UPDATE
子句指定在将引用表中的引用列更新为新值时要执行的操作。如果更新了行,但实际上没有更改引用列,则不会执行任何操作。除了NO ACTION
检查之外的其他引用操作都不能延迟,即使约束被声明为可延迟的。每个子句都有以下可能的动作
NO ACTION
#产生一个错误,指示删除或更新将导致外键约束违规。如果约束被延迟,则如果仍然存在任何引用行,则在约束检查时会产生此错误。这是默认操作。
RESTRICT
#产生一个错误,指示删除或更新将导致外键约束违规。这与NO ACTION
相同,只是检查不可延迟。
CASCADE
#分别删除任何引用已删除行的行,或将引用列的值更新为引用列的新值。
SET NULL [ ( column_name
[, ... ] ) ]
#将所有引用列或引用列的指定子集设置为 null。只能为ON DELETE
操作指定列的子集。
SET DEFAULT [ ( column_name
[, ... ] ) ]
#将所有引用列或引用列的指定子集设置为其默认值。只能为ON DELETE
操作指定列的子集。(如果默认值不为 null,则引用表中必须有一行与默认值匹配,否则操作将失败。)
如果引用列经常更改,则最好向引用列添加索引,以便可以更有效地执行与外键约束关联的引用操作。
DEFERRABLE
NOT DEFERRABLE
#这控制约束是否可以延迟。不可延迟的约束将在每个命令之后立即进行检查。可延迟约束的检查可以推迟到事务结束时(使用SET CONSTRAINTS
命令)。NOT DEFERRABLE
是默认值。目前,只有UNIQUE
、PRIMARY KEY
、EXCLUDE
和REFERENCES
(外键)约束接受此子句。NOT NULL
和CHECK
约束不可延迟。请注意,可延迟约束不能用作包含ON CONFLICT DO UPDATE
子句的INSERT
语句中的冲突仲裁者。
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
#这是用于声明表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的更多信息,请参见第 65.2 节)。如果设置了表参数值并且未设置等效的toast.
参数,则TOAST表将使用表参数值。不支持为分区表指定这些参数,但您可以为各个叶子分区指定它们。
fillfactor
(integer
) #表的fillfactor是介于10到100之间的百分比。100(完全打包)是默认值。当指定较小的fillfactor时,INSERT
操作仅将表页打包到指定的百分比;每个页面的剩余空间保留用于更新该页面的行。这使UPDATE
有机会将更新的行副本放置在与原始行相同的页面上,这比将其放置在不同的页面上更有效,并且使仅堆元组更新更有可能。对于从不更新其条目的表,完全打包是最佳选择,但在更新频繁的表中,较小的fillfactor更合适。此参数不能设置为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
) #启用或禁用真空以尝试截断此表末尾的任何空页。默认值为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_analyze_threshold
(integer
) #autovacuum_analyze_threshold参数的每个表值。
autovacuum_analyze_scale_factor
(浮点数
) #autovacuum_analyze_scale_factor 参数的每个表值。
autovacuum_vacuum_cost_delay
, toast.autovacuum_vacuum_cost_delay
(浮点数
) #autovacuum_vacuum_cost_delay 参数的每个表值。
autovacuum_vacuum_cost_limit
, toast.autovacuum_vacuum_cost_limit
(整数
) #autovacuum_vacuum_cost_limit 参数的每个表值。
autovacuum_freeze_min_age
, toast.autovacuum_freeze_min_age
(整数
) #vacuum_freeze_min_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围 autovacuum_freeze_max_age 设置一半的每个表 autovacuum_freeze_min_age
参数。
autovacuum_freeze_max_age
, toast.autovacuum_freeze_max_age
(整数
) #autovacuum_freeze_max_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围设置的每个表 autovacuum_freeze_max_age
参数(只能将其设置为更小)。
autovacuum_freeze_table_age
, toast.autovacuum_freeze_table_age
(整数
) #vacuum_freeze_table_age 参数的每个表值。
autovacuum_multixact_freeze_min_age
, toast.autovacuum_multixact_freeze_min_age
(整数
) #vacuum_multixact_freeze_min_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围 autovacuum_multixact_freeze_max_age 设置一半的每个表 autovacuum_multixact_freeze_min_age
参数。
autovacuum_multixact_freeze_max_age
, toast.autovacuum_multixact_freeze_max_age
(整数
) #autovacuum_multixact_freeze_max_age 参数的每个表值。请注意,autovacuum 将忽略大于系统范围设置的每个表 autovacuum_multixact_freeze_max_age
参数(只能将其设置为更小)。
autovacuum_multixact_freeze_table_age
, toast.autovacuum_multixact_freeze_table_age
(整数
) #vacuum_multixact_freeze_table_age 参数的每个表值。
log_autovacuum_min_duration
, toast.log_autovacuum_min_duration
(整数
) #log_autovacuum_min_duration 参数的每个表值。
user_catalog_table
(布尔值
) #将表声明为逻辑复制的附加目录表。有关详细信息,请参阅第 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
定义唯一表约束。唯一表约束可以针对表的1列或多列定义
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
约束)不存在这种额外的自由度,因为关联的索引与约束同名,并且索引名称必须在同一模式内的所有关系中唯一。
目前,PostgreSQL 根本不记录非空约束的名称,因此它们不受唯一性限制。这可能会在将来的版本中更改。
通过 INHERITS
子句实现的多重继承是 PostgreSQL 的语言扩展。SQL:1999 及更高版本使用不同的语法和语义定义了单一继承。SQL:1999 风格的继承尚未得到 PostgreSQL 的支持。
PostgreSQL 允许创建没有列的表(例如,CREATE TABLE foo();
)。这是对 SQL 标准的扩展,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 的扩展。