CREATE TABLE — 定义一个新表
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ]table_name
( [ {column_name
data_type
[ COLLATEcollation
] [column_constraint
[ ... ] ] |table_constraint
| LIKEsource_table
[like_option
... ] } [, ... ] ] ) [ INHERITS (parent_table
[, ... ] ) ] [ PARTITION BY { RANGE | LIST } ( {column_name
| (expression
) } [ COLLATEcollation
] [opclass
] [, ... ] ) ] [ WITH (storage_parameter
[=value
] [, ... ] ) | WITH OIDS | 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 } ( {column_name
| (expression
) } [ COLLATEcollation
] [opclass
] [, ... ] ) ] [ WITH (storage_parameter
[=value
] [, ... ] ) | WITH OIDS | 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
[ PARTITION BY { RANGE | LIST } ( {column_name
| (expression
) } [ COLLATEcollation
] [opclass
] [, ... ] ) ] [ WITH (storage_parameter
[=value
] [, ... ] ) | WITH OIDS | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACEtablespace_name
] 其中column_constraint
是: [ CONSTRAINTconstraint_name
] { NOT NULL | NULL | CHECK (expression
) [ NO INHERIT ] | DEFAULTdefault_expr
| GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ (sequence_options
) ] | UNIQUEindex_parameters
| PRIMARY KEYindex_parameters
| REFERENCESreftable
[ (refcolumn
) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEaction
] [ ON UPDATEaction
] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]table_constraint
是: [ CONSTRAINTconstraint_name
] { CHECK (expression
) [ NO INHERIT ] | UNIQUE (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 DELETEaction
] [ ON UPDATEaction
] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]like_option
是: { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | IDENTITY | INDEXES | STORAGE | COMMENTS | ALL }partition_bound_spec
是: IN ( {numeric_literal
|string_literal
| NULL } [, ...] ) | FROM ( {numeric_literal
|string_literal
| MINVALUE | MAXVALUE } [, ...] ) TO ( {numeric_literal
|string_literal
| MINVALUE | MAXVALUE } [, ...] )UNIQUE
、PRIMARY KEY
以及EXCLUDE
约束中的index_parameters
是: [ WITH (storage_parameter
[=value
] [, ... ] ) ] [ USING INDEX TABLESPACEtablespace_name
] 一个EXCLUDE
约束中的exclude_element
是: {column_name
| (expression
) } [opclass
] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
CREATE TABLE
将在当前数据库中创建一个新的、初始为空的表。该表将由发出该命令的用户所拥有。
如果给定了一个模式名(例如CREATE TABLE myschema.mytable ...
),那么该表被创建在指定的模式中。否则它被创建在当前模式中。临时表存在于一个特殊的模式中,因此在创建一个临时表时不能给定一个模式名。该表的名称必须与同一个模式中的任何其他表、序列、索引、视图或外部表的名称区分开。
CREATE TABLE
也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中任何已有数据类型的名称。
可选的约束子句指定一个插入或更新操作要成功,新的或更新过的行必须满足的约束(测试)。一个约束是一个 SQL 对象,它帮助以多种方式定义表中的合法值集合。
有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列时方便书写的记号习惯。
要能创建一个表,你必须分别具有所有列类型或OF
子句中类型的USAGE
特权。
TEMPORARY
or TEMP
如果指定,该表被创建为一个临时表。临时表会被在会话结束时自动被删除,或者也可以选择在当前事务结束时删除(见下文的ON COMMIT
)。当临时表存在时,已有的同名持久表将对于当前会话不可见,不过可以使用模式限定的名称进行引用。在一个临时表上创建的任何索引也自动地变为临时的。
自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE
。
可以选择将GLOBAL
或LOCAL
写在TEMPORARY
或TEMP
的前面。这当前在PostgreSQL中没有区别并且已被废弃,见兼容性。
UNLOGGED
如果指定,该表被创建为一个不受日志记录的表。被写入到不做日志的表中的数据不会被写到预写式日志中(见第 30 章),这让它们比普通表快非常多。不过,它们在崩溃时是不安全的:一个不做日志的表在一次崩溃或非干净关闭之后会被自动地截断。一个不做日志的表中的内容也不会被复制到后备服务器中。在一个不做日志的表上创建的任何索引也会自动地不被日志记录。
IF NOT EXISTS
如果一个同名关系已经存在,不要抛出一个错误。在这种情况下会发出一个提示。注意这不保证现有的关系是和将要被创建的表相似的东西。
table_name
要被创建的表名(可以选择用模式限定)。
OF type_name
创建一个类型化的表,它的结构取自于指定的组合类型(名字可以选择用模式限定)。一个类型化的表和它的类型绑定在一起,例如如果类型被删除,该表也将被删除(用DROP TYPE ... CASCADE
)。
当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在CREATE TABLE
命令中直接指定。但是CREATE TABLE
命令可以对表增加默认值和约束,并且可以指定存储参数。
PARTITION OF parent_table
FOR VALUES partition_bound_spec
将表创建为指定父表的分区。
partition_bound_spec
必须对应于父表的分区方法和分区键,并且必须不能与该父表的任何现有分区重叠。
形式用于列表分区,FROM
和TO
形式用于范围分区。
在partition_bound_spec
中指定的每个值都是一个文字、NULL
、MINVALUE
或MAXVALUE
。每个文字值必须是可对相应的分区键列类型强制的数字常量,
或者是该类型的有效输入的字符串文字。
在创建列表分区时,可以指定NULL
来表示分区允许分区键列为空。
但是,给定父表不能有多于一个这样的列表分区。无法为范围分区指定
NULL
。
创建范围分区时,由FROM
指定的下限是一个包含范围,
而用TO
指定的上限是排除范围。也就是说,
在FROM
列表中指定的值是该分区的相应分区键列的有效值,
而TO
列表中的值不是。请注意,
必须根据按行比较的规则来理解此语句(第 9.23.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)
不是空的范围;
它只允许存储一个值— "infinity"。
分区必须与其所属的分区表的字段名和类型相同。如果父表声明为WITH
OIDS
那么所有的分区必须具有OID;父表的OID字段和其他字段一样被所有分区继承。
对分区表字段名或类型的修改,或者OID字段的添加或删除,将自动传播到所有分区。
CHECK
约束将自动被每一个分区继承,但是单独的分区可以指定额外的
CHECK
约束;与父表相同名称和条件的额外约束将被父表约束合并。
可以为每个分区分别指定默认值。
插入分区表中的行将自动路由到正确的分区。如果不存在合适的分区,则会发生错误。 另外,如果更新给定分区中的行由于新的分区键值而要求它移动到另一分区,则会发生错误。
像TRUNCATE这样的操作通常会影响一个表及其所有继承子级,这些操作将级联到所有分区,
但也可能在单个分区上执行。请注意,使用DROP TABLE
删除分区需要在父表上采用ACCESS EXCLUSIVE
锁。
column_name
要在新表中创建的一列的名称。
data_type
该列的数据类型。这可以包括数组说明符。更多关于PostgreSQL支持的数据类型,请参考第 8 章。
COLLATE collation
COLLATE
子句为该列(必须是一种可排序数据类型)赋予一个排序规则。如果没有指定,将使用该列数据类型的默认排序规则。
INHERITS ( parent_table
[, ... ] )
可选的INHERITS
子句指定一个表的列表,新表将从其中自动地继承所有列。父表可以是普通表或者外部表。
INHERITS
的使用在新的子表和它的父表之间创建一种持久的关系。对于父表的模式修改通常也会传播到子表,并且默认情况下子表的数据会被包括在对父表的扫描中。
如果在多个父表中存在同名的列,除非父表中每一个这种列的数据类型都能匹配,否则会报告一个错误。如果没有冲突,那么重复列会被融合来形成新表中的一个单一列。如果新表中的列名列表包含一个也是继承而来的列名,该数据类型必须也匹配继承的列,并且列定义会被融合成一个。如果新表显式地为列指定了任何默认值,这个默认值将覆盖来自该列继承声明中的默认值。否则,任何父表都必须为该列指定相同的默认值,或者会报告一个错误。
CHECK
约束本质上也采用和列相同的方式被融合:如果多个父表或者新表定义中包含相同的命名CHECK
约束,这些约束必须全部具有相同的检查表达式,否则将报告一个错误。具有相同名称和表达式的约束将被融合成一份拷贝。一个父表中的被标记为NO INHERIT
的约束将不会被考虑。注意新表中一个未命名的CHECK
约束将永远不会被融合,因为那样总是会为它选择一个唯一的名字。
列的STORAGE
设置也会从父表复制过来。
如果父表中的列是标识列,那么该属性不会被继承。如果需要, 可以将子表中的列声明为标识列。
PARTITION BY { RANGE | LIST } ( { column_name
| ( expression
) } [ opclass
] [, ...] )
可选的PARTITION BY
子句指定了对表进行分区的策略。
这样创建的表称为分区表。
带括号的列或表达式列表形成表的分区键。
使用范围分区时,分区键可以包含多个列或表达式(最多32个,但在构建
PostgreSQL时可以更改此限制),但对于列表分区,
分区键必须由单个列或表达式组成。如果在创建分区表时未指定B树操作符类,
则将使用该数据类型的默认B树操作符类。如果没有,则会报告错误。
分区表被分成多个子表(称为分区),它们是使用单独的CREATE TABLE
命令创建的。
分区表本身是空的。插入到表中的数据行将根据分区键中的列或表达式的值路由到分区。
如果没有现有的分区与新行中的值匹配,则会报告错误。
分区表不支持UNIQUE
、
PRIMARY KEY
、EXCLUDE
或
FOREIGN KEY
约束;不过,可以在单个分区中定义这些约束。
LIKE source_table
[ like_option
... ]
LIKE
指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。
和INHERITS
不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表,并且不可能在原始表的扫描中包括新表的数据。
只有INCLUDING DEFAULTS
被指定时,被拷贝的列定义的默认表达式才会被拷贝。默认的行为是排除默认表达式,导致新表中被拷贝过来的列的默认值为空值。注意,如果拷贝的默认值调用了数据库修改函数(如nextval
),则可能在原始表和新表之间创建功能联系。
仅在声明了INCLUDING IDENTITY
的情况下拷贝复制字段定义的标识声明。
为新表的每个标识列创建一个新的序列,与旧表相关的序列区分开。
非空约束总是会被复制到新表。CHECK
约束只有在INCLUDING CONSTRAINTS
被指定时才会被复制。列约束和表约束之间没有区别对待。
只有INCLUDING INDEXES
被指定时,原始表上的索引、PRIMARY KEY
、UNIQUE
以及EXCLUDE
约束将被创建在新表上。新索引和约束的名称将根据默认规则选定,而不管原始的名称如何(这种行为可以避免新索引重名导致的失败)。
只有INCLUDING STORAGE
被指定时,复制而来的列定义的STORAGE
设置才会被复制。默认行为会排除STORAGE
设置,导致新表中复制而来的列具有与类型相关的默认设置。更多关于STORAGE
设置的信息,请见第 66.2 节。
只有INCLUDING COMMENTS
被指定时,复制而来的列、约束和索引的注释才会被拷贝。默认行为是排除注释,这导致新表中复制而来的列和约束没有注释。
INCLUDING ALL
是
INCLUDING DEFAULTS INCLUDING IDENTITY INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS
的简写形式。
注意和INHERITS
不同,用LIKE
拷贝的列和约束不会和相似的命名列及约束融合。如果显式指定了相同的名称或者在另一个LIKE
子句中指定了相同的名称,将会发出一个错误。
LIKE
子句也能被用来从视图、外部表或组合类型拷贝列定义。不适合的选项(例如来自视图的INCLUDING INDEXES
)会被忽略。
CONSTRAINT constraint_name
一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似列必须为正
的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如果没有指定约束名,系统将生成一个。
NOT NULL
该列不允许包含空值。
NULL
该列允许包含空值。这是默认情况。
这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。
CHECK ( expression
) [ NO INHERIT ]
CHECK
指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。
当前,CHECK
表达式不能包含子查询,也不能引用当前行的列之外的变量。可以引用系统列tableoid
,但不能引用其他系统列。
一个被标记为NO INHERIT
的约束将不会传播到子表。
当一个表有多个CHECK
约束时,检查完NOT NULL
约束后,对于每一行会以它们名称的字母表顺序来进行检查(版本 9.5 之前的PostgreSQL对于CHECK
约束不遵从任何特定的引发顺序)。
DEFAULT
default_expr
DEFAULT
子句为出现在其定义中的列赋予一个默认数据。该值是可以使用变量的表达式(不允许用子查询和对其他列的交叉引用)。默认值表达式的数据类型必须匹配列的数据类型。
默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options
) ]
该子句将列创建为标识列。 它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中获取值。
子句ALWAYS
和BY DEFAULT
确定在
INSERT
语句中,序列值如何优先于用户指定的值。
如果指定了ALWAYS
,则只有在INSERT
语句指定OVERRIDING SYSTEM VALUE
时才接受用户指定的值。
如果指定了BY DEFAULT
,则用户指定的值优先。
有关详细信息,请参见INSERT。
(在COPY
命令中,无论此设置如何,都始终使用用户指定的值。)
可选的sequence_options
子句可用于覆盖序列的选项。
有关详细信息,请参见CREATE SEQUENCE。
UNIQUE
(列约束)UNIQUE ( column_name
[, ... ] )
(表约束) UNIQUE
约束指定一个表中的一列或多列组成的组包含唯一的值。唯一表约束的行为与列约束的行为相同,只是表约束能够跨越多列。
对于一个唯一约束的目的来说,空值不被认为是相等的。
每一个唯一表约束必须命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不相同(否则它将是一个被列举了两次的约束)。
PRIMARY KEY
(列约束)PRIMARY KEY ( column_name
[, ... ] )
(表约束) PRIMARY KEY
约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个主键,可以作为列约束或表约束。
主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余的并且会被丢弃)。
PRIMARY KEY
强制的数据约束可以看成是UNIQUE
和NOT NULL
的组合,不过把一组列标识为主键也为模式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。
EXCLUDE [ USING index_method
] ( exclude_element
WITH operator
[, ... ] ) index_parameters
[ WHERE ( predicate
) ]
EXCLUDE
子句定一个排除约束,它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,不是所有的比较都将会返回TRUE
。如果所有指定的操作符都测试相等,这就等价于一个UNIQUE
约束,尽管一个普通的唯一约束将更快。不过,排除约束能够指定比简单相等更通用的约束。例如,你可以使用&&
操作符指定一个约束,要求表中没有两行包含相互覆盖的圆(见 第 8.8 节)。
排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法index_method
的一个适当的操作符类(见第 11.9 节)相关联。操作符被要求是交换的。每一个exclude_element
可以选择性地指定一个操作符类或者顺序选项,这些在CREATE INDEX中有完整描述。
访问方法必须支持amgettuple
(见第 60 章),目前这意味着GIN无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是GiST或SP-GiST。
predicate
允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周围的圆括号是必须的。
REFERENCES reftable
[ ( refcolumn
) ] [ MATCH matchtype
] [ ON DELETE action
] [ ON UPDATE action
]
(列约束)FOREIGN KEY ( column_name
[, ... ] )
REFERENCES reftable
[ ( refcolumn
[, ... ] ) ]
[ MATCH matchtype
]
[ ON DELETE action
]
[ ON UPDATE action
]
(表约束) 这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在被引用列上的值。如果refcolumn
列表被忽略,将使用reftable
的主键。被引用列必须是被引用表中一个非可延迟唯一约束或主键约束的列。
用户必须在被引用的表(或整个表或特定的引用列)上拥有REFERENCES
权限。
注意外键约束不能在临时表和永久表之间定义。
被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。有三种匹配类型: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
将引用列设置为空。
SET DEFAULT
设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认值,否则该操作将会失败)。
如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效地被执行。
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命令修改。
WITH ( storage_parameter
[= value
] [, ... ] )
这个子句为一个表或索引指定可选的存储参数,详见存储参数。一个表的WITH
子句还可以包括OIDS=TRUE
(或者只包括OIDS
)来指定新表的行应该具有被分配的 OID(对象标识符),或者包括OIDS=FALSE
来指定新表的行不具有 OID。如果没有指定OIDS
,默认设置取决于default_with_oids配置参数(如果新表是从任何具有 OID 的表继承而来,那么即使该命令要求OIDS=FALSE
也会强制使用OIDS=TRUE
)。
如果指定或者蕴含了OIDS=FALSE
,新表就不会存储 OID 并且对插入其中的一个新行不会分配 OID。这通常值得考虑,因为它将减少 OID 消耗并且因而推迟 32 为 OID 计数器的回卷。一旦计数器回卷,OID 就不再能被假定为唯一,这就使它们不那么有用了。另外,从一个表中排除 OID 可以减少存储该表所需的磁盘空间,减少的量是每行减少 4 字节(在大部分机器上),这也略微提高了性能。
要在表被创建后从中移除 OID,使用ALTER TABLE.
WITH OIDS
WITHOUT OIDS
这些语法已被荒废,它们分别等效于WITH (OIDS)
和WITH (OIDS=FALSE)
。如果你希望同时给出一个OIDS
设置和存储参数,你必须使用WITH ( ... )
语法,见上文。
ON COMMIT
临时表在一个事务块结束时的行为由ON COMMIT
控制。三种选项是:
PRESERVE ROWS
在事务结束时不采取特殊的动作。这是默认行为。
DELETE ROWS
在每一个事务块结束时将删除临时表中的所有行。实质上,在每一次提交时会完成一次自动的TRUNCATE。
DROP
在当前事务块结束时将删除临时表。
TABLESPACE tablespace_name
tablespace_name
是新表要创建于其中的表空间名称。如果没有指定,将参考default_tablespace,或者如果表是临时的则参考temp_tablespaces。
USING INDEX TABLESPACE tablespace_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 表设置。
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
才更有用。
autovacuum_vacuum_threshold
, toast.autovacuum_vacuum_threshold
(integer
)autovacuum_vacuum_threshold参数对于每个表的值。
autovacuum_vacuum_scale_factor
, toast.autovacuum_vacuum_scale_factor
(float4
)autovacuum_vacuum_scale_factor参数对于每个表的值。
autovacuum_analyze_threshold
(integer
)autovacuum_analyze_threshold参数对于每个表的值。
autovacuum_analyze_scale_factor
(float4
)autovacuum_analyze_scale_factor参数对于每个表的值。
autovacuum_vacuum_cost_delay
, toast.autovacuum_vacuum_cost_delay
(integer
)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
)声明该表是一个用于逻辑复制目的的额外的目录表。详见第 48.6.2 节。不能对 TOAST 表设置这个参数。
我们不推荐在新应用中使用 OID:在可能要用到的地方,使用一个标识列或者其他序列生成器作为表的主键会更好。不过,如果你的应用确实需要用到 OID 来标识一个表的特定行,我们推荐在表的oid
列上创建一个唯一约束,来确保表中的 OID 在计数器回卷后能唯一标识行。如果你需要一个数据库范围的唯一标识符,要避免假定 OID 在表之间也是唯一的,应该用tableoid
和行 OID 的组合来实现该目的。
我们不推荐对没有主键的表使用OIDS=FALSE
,因为没有 OID 或 唯一数据键,就很难标识特定的行。
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 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
命令遵从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扩展。
NULL
“约束” NULL
“约束”(实际上是一个非约束)是一个PostgreSQL对 SQL 标准的扩展,它也被包括(以及对称的NOT NULL
约束)在一些其他的数据库系统中以实现兼容性。因为它是任意列的默认值,它的存在就像噪声一样。
通过INHERITS
子句的多继承是一种PostgreSQL的语言扩展。SQL:1999 以及之后的标准使用一种不同的语法和不同的语义定义了单继承。SQL:1999-风格的继承还没有被PostgreSQL。
PostgreSQL允许创建一个没有列的表(例如CREATE TABLE foo();
)。这是一个对于 SQL 标准的扩展,它不允许零列表。零列表本身并不是很有用,但是不允许它们会为ALTER TABLE DROP COLUMN
带来奇怪的特殊情况,因此忽略这种规则限制看起来更加整洁。
PostgreSQL允许一个表拥有多个标识列。
该标准指定一个表最多只能有一个标识列。这主要是为了给模式更改或迁移提供更大的灵活性。
请注意,INSERT
命令仅支持一个适用于整个语句的覆盖子句,
因此不支持具有不同行为的多个标识列。
LIKE
子句 虽然 SQL 标准中有一个LIKE
子句,但是PostgreSQL接受的很多LIKE
子句选项却不在标准中,并且有些标准中的选项也没有被PostgreSQL实现。
WITH
子句 WITH
子句是一个PostgreSQL扩展,存储参数和 OID 都不在标准中。
PostgreSQL的表空间概念不是标准的一部分。因此,子句TABLESPACE
和USING INDEX TABLESPACE
是扩展。
类型化的表实现了 SQL 标准的一个子集。根据标准,一个类型化的表具有与底层组合类型相对应的列,以及其他的“自引用列”。PostgreSQL 不显式支持这些自引用列,但是可以使用 OID 特性获得相同的效果。
PARTITION BY
子句 PARTITION BY
子句是PostgreSQL的一个扩展。
PARTITION OF
子句 PARTITION OF
子句PostgreSQL的一个扩展。