## 更改表 ALTER TABLE — 更改表的定义 ## 概要 ``` ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] action [, ... ] ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] RENAME [ COLUMN ] column_name TO new_column_name ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] RENAME CONSTRAINT constraint_name TO new_constraint_name ALTER TABLE [ IF EXISTS ] name RENAME TO new_name ALTER TABLE [ IF EXISTS ] name SET SCHEMA new_schema ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] SET TABLESPACE new_tablespace [ NOWAIT ] ALTER TABLE [ IF EXISTS ] name ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } ALTER TABLE [ IF EXISTS ] name DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ] where action is one of: ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ] ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ] ALTER [ COLUMN ] column_name SET DEFAULT expression ALTER [ COLUMN ] column_name DROP DEFAULT ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL ALTER [ COLUMN ] column_name DROP EXPRESSION [ IF EXISTS ] ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...] ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ] ALTER [ COLUMN ] column_name SET STATISTICS integer ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] ) ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] ) ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ALTER [ COLUMN ] column_name SET COMPRESSION compression_method ADD table_constraint [ NOT VALID ] ADD table_constraint_using_index ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] VALIDATE CONSTRAINT constraint_name DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] DISABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE REPLICA TRIGGER trigger_name ENABLE ALWAYS TRIGGER trigger_name DISABLE RULE rewrite_rule_name ENABLE RULE rewrite_rule_name ENABLE REPLICA RULE rewrite_rule_name ENABLE ALWAYS RULE rewrite_rule_name DISABLE ROW LEVEL SECURITY ENABLE ROW LEVEL SECURITY FORCE ROW LEVEL SECURITY NO FORCE ROW LEVEL SECURITY CLUSTER ON index_name SET WITHOUT CLUSTER SET WITHOUT OIDS SET TABLESPACE new_tablespace SET { LOGGED | UNLOGGED } SET ( storage_parameter [= value] [, ... ] ) RESET ( storage_parameter [, ... ] ) INHERIT parent_table NO INHERIT parent_table OF type_name NOT OF OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING } and partition_bound_spec is: IN ( partition_bound_expr [, ...] ) | FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUS numeric_literal, REMAINDER numeric_literal ) and column_constraint is: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | UNIQUE index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | UNIQUE ( column_name [, ... ] ) index_parameters | PRIMARY KEY ( column_name [, ... ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] and table_constraint_using_index is: [ CONSTRAINT constraint_name ] { UNIQUE | PRIMARY KEY } USING INDEX index_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are: [ INCLUDE ( column_name [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ USING INDEX TABLESPACE tablespace_name ] exclude_element in an EXCLUDE constraint is: { column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] ``` ## 描述 `更改表`更改现有表的定义。下面描述了几个子窗体。请注意,每个子表单所需的锁定级别可能不同。一个`访问独家`除非明确说明,否则会获取锁。当给出多个子命令时,获得的锁将是任何子命令所需的最严格的锁。 `添加列 [如果不存在]` 此表单使用与以下相同的语法向表中添加一个新列[`创建表`](sql-createtable.html).如果`如果不存在`已指定且已存在具有此名称的列,则不会引发错误。 `删除列 [如果存在]` 此表单从表中删除一列。涉及该列的索引和表约束也将被自动删除。如果删除列会导致统计信息仅包含单个列的数据,则引用已删除列的多变量统计信息也将被删除。你需要说`级联`如果表之外的任何内容取决于列,例如外键引用或视图。如果`如果存在`指定并且该列不存在,则不会引发错误。在这种情况下,将发出通知。 `设置数据类型` 此表单更改表格列的类型。通过重新解析最初提供的表达式,涉及该列的索引和简单表约束将自动转换为使用新的列类型。可选的`整理`子句指定新列的排序规则;如果省略,则排序规则是新列类型的默认值。可选的`使用`子句指定如何从旧列值计算新列值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。一种`使用`如果没有从旧类型到新类型的隐式或赋值强制转换,则必须提供子句。 `放`/`删除默认值` 这些表单设置或删除列的默认值(其中删除相当于将默认值设置为 NULL)。新的默认值仅适用于后续`插入`或者`更新`命令;它不会导致表中已经存在的行发生更改。 `放`/`删除不为空` 这些形式改变了列被标记为允许空值还是拒绝空值。 `设置非空`只能应用于列,前提是表中的任何记录都不包含`空值`列的值。通常这是在检查期间`更改表`通过扫描整个表格;然而,如果一个有效的`查看`发现约束证明不`空值`可以存在,则跳过表扫描。 如果此表是分区,则无法执行`删除不为空`如果已标记,则在列上`非空`在父表中。放下`非空`来自所有分区的约束,执行`删除不为空`在父表上。即使没有`非空`constraint on the parent, such a constraint can still be added to individual partitions, if desired; that is, the children can disallow nulls even if the parent allows them, but not the other way around. `DROP EXPRESSION [ IF EXISTS ]` This form turns a stored generated column into a normal base column. Existing data in the columns is retained, but future changes will no longer apply the generation expression. If`DROP EXPRESSION IF EXISTS`is specified and the column is not a stored generated column, no error is thrown. In this case a notice is issued instead. `ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY`\ `SET GENERATED { ALWAYS | BY DEFAULT }`\ `DROP IDENTITY [ IF EXISTS ]` These forms change whether a column is an identity column or change the generation attribute of an existing identity column. See[`CREATE TABLE`](sql-createtable.html)for details. Like`SET DEFAULT`, these forms only affect the behavior of subsequent`INSERT`and`UPDATE`commands; they do not cause rows already in the table to change. If`DROP IDENTITY IF EXISTS`is specified and the column is not an identity column, no error is thrown. In this case a notice is issued instead. `SET *`sequence_option`*`\ `RESTART` These forms alter the sequence that underlies an existing identity column.*`sequence_option`*is an option supported by[`ALTER SEQUENCE`](sql-altersequence.html)such as`增量`. `设置统计` 这种形式为后续的每列统计收集目标设置[`分析`](sql-analyze.html)操作。目标可在 0 到 10000 范围内设置;或者,将其设置为 -1 以恢复使用系统默认统计目标 ([默认\_统计数据\_目标](runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET))。有关 PostgreSQL 查询计划器使用统计信息的更多信息,请参阅[第 14.2 节](planner-stats.html). `设置统计`获得一个`共享更新独家`锁。 `放 ( *`属性选项`* = *`价值`* [, ... ] )`\ `重置 ( *`属性选项`* [, ... ] )` 此表单设置或重置每个属性选项。目前,唯一定义的每个属性选项是`n_distinct`和`n_distinct_inherited`,它覆盖了后续所做的不同值的数量估计[`分析`](sql-analyze.html)操作。`n_distinct`影响表本身的统计信息,而`n_distinct_inherited`影响为表及其继承子级收集的统计信息。当设置为正值时,`分析`将假定该列正好包含指定数量的不同非空值。当设置为负值时,必须大于或等于 -1,`分析`将假设列中不同的非空值的数量与表的大小成线性关系;确切的计数是通过将估计的表大小乘以给定数字的绝对值来计算的。例如,值 -1 意味着列中的所有值都是不同的,而值 -0.5 意味着每个值平均出现两次。当表的大小随时间变化时,这可能很有用,因为直到查询计划时间才执行乘以表中的行数。指定值 0 以恢复正常估计不同值的数量。有关 PostgreSQL 查询计划器使用统计信息的更多信息,请参阅[第 14.2 节](planner-stats.html). 更改每个属性选项会获得`共享更新独家`锁。 `设置存储` [](<>) 此表单设置列的存储模式。这控制此列是内联保存还是保存在辅助 TOAST 表中,以及是否应压缩数据。`清楚的`必须用于固定长度的值,例如`整数`并且是内联的,未压缩的。`主要的`用于内联的可压缩数据。`外部的`用于外部未压缩数据,并且`扩展`用于外部压缩数据。`扩展`是大多数支持非`清楚的`贮存。用于`外部的`将使子字符串操作非常大`文本`和`拜茶`值运行得更快,但会增加存储空间。注意`设置存储`它本身不会改变表格中的任何内容,它只是设置在未来表格更新期间要采用的策略。看[第 70.2 节](storage-toast.html)了解更多信息。 `设置压缩 *`压缩方法`*` 此表单设置列的压缩方法,确定将来插入的值将如何压缩(如果存储模式完全允许压缩)。这不会导致表被重写,因此现有数据仍可能使用其他压缩方法进行压缩。如果表是用 pg 恢复的\_恢复,然后使用配置的压缩方法重写所有值。但是,当从另一个关系插入数据时(例如,通过`插入...选择`),源表中的值不一定会被解压,因此任何先前压缩的数据都可能保留其现有的压缩方法,而不是使用目标列的压缩方法重新压缩。支持的压缩方法是`pglz`和`lz4`.(`lz4`仅在以下情况下可用`--with-lz4`在构建 PostgreSQL 时使用。)此外,*`压缩方法`*可`default`, which selects the default behavior of consulting the[default_toast_compression](runtime-config-client.html#GUC-DEFAULT-TOAST-COMPRESSION)setting at the time of data insertion to determine the method to use. `ADD *`table_constraint`* [ NOT VALID ]` This form adds a new constraint to a table using the same constraint syntax as[`CREATE TABLE`](sql-createtable.html), plus the option`NOT VALID`, which is currently only allowed for foreign key and CHECK constraints. Normally, this form will cause a scan of the table to verify that all existing rows in the table satisfy the new constraint. But if the`NOT VALID`option is used, this potentially-lengthy scan is skipped. The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a matching row in the referenced table, in the case of foreign keys, or they'll fail unless the new row matches the specified check condition). But the database will not assume that the constraint holds for all rows in the table, until it is validated by using the`VALIDATE CONSTRAINT`option. See[Notes](sql-altertable.html#SQL-ALTERTABLE-NOTES)below for more information about using the`NOT VALID`option. Although most forms of`ADD *`table_constraint`*`require an`访问独家`锁,`添加外键`只需要一个`共享行独家`锁。注意`添加外键`还获得了一个`共享行独家`除了在声明约束的表上锁定之外,还锁定被引用的表。 将唯一键或主键约束添加到分区表时会应用其他限制;看[`创建表`](sql-createtable.html).此外,可能不会声明分区表上的外键约束`无效`目前。 `添加 *`table_constraint_using_index`*` 这种形式增加了一个新的`首要的关键`要么`独特`基于现有唯一索引的表的约束。索引的所有列都将包含在约束中。 索引不能有表达式列,也不能是部分索引。此外,它必须是具有默认排序顺序的 b 树索引。这些限制确保索引等同于由常规构建的索引`添加主键`要么`添加唯一`命令。 如果`首要的关键`已指定,并且索引的列尚未标记`非空`, 那么这个命令会尝试做`ALTER COLUMN SET NOT NULL`针对每个这样的列。这需要全表扫描来验证列不包含空值。在所有其他情况下,这是一个快速操作。 如果提供了约束名称,则索引将被重命名以匹配约束名称。否则,约束将被命名为与索引相同。 执行此命令后,索引由约束“拥有”,就像索引已由常规构建一样`添加主键`要么`添加唯一`命令。特别是,删除约束也会使索引消失。 分区表目前不支持这种形式。 ### 笔记 在需要添加新约束而又不长时间阻塞表更新的情况下,使用现有索引添加约束可能会很有帮助。为此,请使用创建索引`并发创建索引`,然后使用此语法将其安装为官方约束。请参见下面的示例。 `改变约束` 这种形式改变了先前创建的约束的属性。目前只有外键约束可以改变。 `验证约束` 此表单验证先前创建为的外键或检查约束`无效`,通过扫描表以确保没有不满足约束的行。如果约束已被标记为有效,则不会发生任何事情。(看[笔记](sql-altertable.html#SQL-ALTERTABLE-NOTES)下面解释了这个命令的用处。) 该命令获取一个`共享更新独家`锁。 `删除约束 [如果存在]` 此表单删除表上的指定约束以及约束下的任何索引。如果`如果存在`is specified and the constraint does not exist, no error is thrown. In this case a notice is issued instead. `DISABLE`/`ENABLE [ REPLICA | ALWAYS ] TRIGGER` These forms configure the firing of trigger(s) belonging to the table. A disabled trigger is still known to the system, but is not executed when its triggering event occurs. For a deferred trigger, the enable status is checked when the event occurs, not when the trigger function is actually executed. One can disable or enable a single trigger specified by name, or all triggers on the table, or only user triggers (this option excludes internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints). Disabling or enabling internally generated constraint triggers requires superuser privileges; it should be done with caution since of course the integrity of the constraint cannot be guaranteed if the triggers are not executed. The trigger firing mechanism is also affected by the configuration variable[session_replication_role](runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE). Simply enabled triggers (the default) will fire when the replication role is “origin” (the default) or “local”. Triggers configured as`ENABLE REPLICA`will only fire if the session is in “replica” mode, and triggers configured as`ENABLE ALWAYS`will fire regardless of the current replication role. The effect of this mechanism is that in the default configuration, triggers do not fire on replicas. This is useful because if a trigger is used on the origin to propagate data between tables, then the replication system will also replicate the propagated data, and the trigger should not fire a second time on the replica, because that would lead to duplication. However, if a trigger is used for another purpose such as creating external alerts, then it might be appropriate to set it to`ENABLE ALWAYS`so that it is also fired on replicas. This command acquires a`SHARE ROW EXCLUSIVE`lock. `DISABLE`/`ENABLE [ REPLICA | ALWAYS ] RULE` These forms configure the firing of rewrite rules belonging to the table. A disabled rule is still known to the system, but is not applied during query rewriting. The semantics are as for disabled/enabled triggers. This configuration is ignored for`ON SELECT`rules, which are always applied in order to keep views working even if the current session is in a non-default replication role. The rule firing mechanism is also affected by the configuration variable[session\_复制\_角色](runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE),类似于上面描述的触发器。 `禁用`/`启用行级安全` 这些表单控制属于表的行安全策略的应用。如果已启用且表不存在任何策略,则应用默认拒绝策略。请注意,即使禁用了行级安全性,表也可以存在策略。在这种情况下,政策将*不是*被应用并且策略将被忽略。也可以看看[`创建政策`](sql-createpolicy.html). `没有力量`/`强制行级安全` 当用户是表所有者时,这些表单控制属于表的行安全策略的应用。如果启用,当用户是表所有者时将应用行级安全策略。如果禁用(默认),则当用户是表所有者时,不会应用行级安全性。也可以看看[`创建政策`](sql-createpolicy.html). `集群开启` 此表单选择未来的默认索引[`簇`](sql-cluster.html)操作。它实际上并没有重新聚集表。 更改集群选项会获得`共享更新独家`锁。 `无簇集` 此表单删除最近使用的[`簇`](sql-cluster.html)表中的索引规范。这会影响未指定索引的未来集群操作。 更改集群选项会获得`共享更新独家`锁。 `无 OID 设置` 用于删除的向后兼容语法`样的`系统栏。作为`样的`无法再添加系统列,这永远不会产生影响。 `设置表空间` 此表单将表的表空间更改为指定的表空间,并将与表关联的数据文件移动到新的表空间。表上的索引(如果有)不会移动;但它们可以单独移动`设置表空间`命令。当应用于分区表时,不会移动任何内容,但之后创建的任何分区`创建表分区`将使用该表空间,除非被`表空间`条款。 表空间中当前数据库中的所有表都可以使用`全部在表空间中`表单,它将先锁定所有要移动的表,然后再移动每个表。这种形式还支持`拥有者`,这只会移动指定角色拥有的表。如果`现在等待`如果指定了选项,则如果无法立即获取所需的所有锁,该命令将失败。请注意,此命令不会移动系统目录;采用`更改数据库`或明确的`更改表`如果需要,可以调用。这`信息模式`关系不被视为系统目录的一部分,将被移动。也可以看看[`CREATE TABLESPACE`](sql-createtablespace.html). `SET { LOGGED | UNLOGGED }` This form changes the table from unlogged to logged or vice-versa (see[`UNLOGGED`](sql-createtable.html#SQL-CREATETABLE-UNLOGGED)). It cannot be applied to a temporary table. `SET ( *`storage_parameter`* [= *`value`*] [, ... ] )` This form changes one or more storage parameters for the table. See[Storage Parameters](sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS)in the[`CREATE TABLE`](sql-createtable.html)documentation for details on the available parameters. Note that the table contents will not be modified immediately by this command; depending on the parameter you might need to rewrite the table to get the desired effects. That can be done with[`VACUUM FULL`](sql-vacuum.html),[`CLUSTER`](sql-cluster.html)or one of the forms of`ALTER TABLE`that forces a table rewrite. For planner related parameters, changes will take effect from the next time the table is locked so currently executing queries will not be affected. `SHARE UPDATE EXCLUSIVE`lock will be taken for fillfactor, toast and autovacuum storage parameters, as well as the planner parameter`parallel_workers`. `RESET ( *`storage_parameter`* [, ... ] )` This form resets one or more storage parameters to their defaults. As with`放`,可能需要重写表才能完全更新表。 `继承 *`父表`*` 此表单将目标表添加为指定父表的新子表。随后,针对父表的查询将包括目标表的记录。要作为子表添加,目标表必须已经包含与父表相同的所有列(它也可以有其他列)。列必须具有匹配的数据类型,并且如果它们具有`非空`父母中的约束,那么他们也必须有`非空`孩子身上的约束。 还必须有所有匹配的子表约束`查看`父级的约束,除了那些标记为不可继承的(即,用`ALTER TABLE ... 添加约束 ... 无继承`) 在父级中,它们被忽略;所有匹配的子表约束不得标记为不可继承。现在`独特`,`首要的关键`, 和`外键`不考虑约束,但将来可能会改变。 `没有继承 *`父表`*` 此表单从指定父表的子表中删除目标表。针对父表的查询将不再包括从目标表中提取的记录。 `的 *`类型名称`*` 此表单将表链接到复合类型,就好像`创建表`已经形成了。表的列名和类型列表必须与复合类型的列表精确匹配。该表不得从任何其他表继承。这些限制确保`创建表`将允许等效的表定义。 `不属于` 此表单将类型化表与其类型分离。 `拥有者` 此表单将表、序列、视图、物化视图或外部表的所有者更改为指定用户。 `副本身份` 此表单更改写入预写日志的信息,以识别更新或删除的行。除非正在使用逻辑复制,否则此选项无效。在所有情况下,都不会记录旧值,除非至少要记录的列之一在行的旧版本和新版本之间有所不同。 `默认` 记录主键列的旧值(如果有)。这是非系统表的默认值。 `使用索引 *`索引名称`*` 记录命名索引所涵盖的列的旧值,这些值必须是唯一的、非部分的、不可延迟的,并且仅包括标记的列`非空`.如果删除此索引,则行为与`没有`. `满的` 记录行中所有列的旧值。 `没有` 不记录有关旧行的信息。这是系统表的默认设置。 `改名` 这`改名`表单更改表(或索引、序列、视图、物化视图或外部表)的名称、表中单个列的名称或表的约束名称。重命名具有基础索引的约束时,索引也会被重命名。对存储的数据没有影响。 `设置架构` 这种形式将表移动到另一个模式中。表列所拥有的关联索引、约束和序列也会被移动。 `附加分区 *`partition_name`* { FOR VALUES *`partition_bound_spec`* | DEFAULT }` This form attaches an existing table (which might itself be partitioned) as a partition of the target table. The table can be attached as a partition for specific values using`FOR VALUES`or as a default partition by using`DEFAULT`. For each index in the target table, a corresponding one will be created in the attached table; or, if an equivalent index already exists, it will be attached to the target table's index, as if`ALTER INDEX ATTACH PARTITION`had been executed. Note that if the existing table is a foreign table, it is currently not allowed to attach the table as a partition of the target table if there are`UNIQUE`indexes on the target table. (See also[CREATE FOREIGN TABLE](sql-createforeigntable.html).) For each user-defined row-level trigger that exists in the target table, a corresponding one is created in the attached table. A partition using`FOR VALUES`uses same syntax for*`partition_bound_spec`*as[`CREATE TABLE`](sql-createtable.html). The partition bound specification must correspond to the partitioning strategy and partition key of the target table. The table to be attached must have all the same columns as the target table and no more; moreover, the column types must also match. Also, it must have all the`NOT NULL`and`CHECK`constraints of the target table. Currently`FOREIGN KEY`constraints are not considered.`UNIQUE`and`首要的关键`如果父表中的约束不存在,则将在分区中创建它们。如果任何一个`查看`被附加的表的约束被标记`没有继承`,命令将失败;必须在没有`没有继承`条款。 如果新分区是常规表,则执行全表扫描以检查表中的现有行是否违反分区约束。可以通过添加一个有效的`查看`对表的约束,在运行此命令之前只允许满足所需分区约束的行。这`查看`约束将用于确定不需要扫描表来验证分区约束。但是,如果任何分区键是表达式并且分区不接受,则这不起作用`空值`价值观。如果附加一个不接受的列表分区`空值`值,还添加`非空`对分区键列的约束,除非它是一个表达式。 如果新分区是外表,则不做任何事情来验证外表中的所有行是否符合分区约束。(见讨论[创建外表](sql-createforeigntable.html)关于外表的约束。) 当表具有默认分区时,定义新分区会更改默认分区的分区约束。默认分区不能包含任何需要移动到新分区的行,并且将被扫描以验证是否不存在任何行。这种扫描,就像对新分区的扫描一样,如果适当的话可以避免`查看`存在约束。也和新分区的扫描一样,默认分区是外表时总是跳过。 附加一个分区会获得一个`共享更新独家`锁定父表,除了`访问独家`锁定正在附加的表和默认分区(如果有)。 Further locks must also be held on all sub-partitions if the table being attached is itself a partitioned table. Likewise if the default partition is itself a partitioned table. The locking of the sub-partitions can be avoided by adding a`CHECK`constraint as described in[Section 5.11.2.2](ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-MAINTENANCE). `DETACH PARTITION *`partition_name`* [ CONCURRENTLY | FINALIZE ]` This form detaches the specified partition of the target table. The detached partition continues to exist as a standalone table, but no longer has any ties to the table from which it was detached. Any indexes that were attached to the target table's indexes are detached. Any triggers that were created as clones of those in the target table are removed.`SHARE`lock is obtained on any tables that reference this partitioned table in foreign key constraints. If`CONCURRENTLY`is specified, it runs using a reduced lock level to avoid blocking other sessions that might be accessing the partitioned table. In this mode, two transactions are used internally. During the first transaction, a`SHARE UPDATE EXCLUSIVE`lock is taken on both parent table and partition, and the partition is marked as undergoing detach; at that point, the transaction is committed and all other transactions using the partitioned table are waited for. Once all those transactions have completed, the second transaction acquires`SHARE UPDATE EXCLUSIVE`on the partitioned table and`ACCESS EXCLUSIVE`on the partition, and the detach process completes. A`CHECK`constraint that duplicates the partition constraint is added to the partition.`CONCURRENTLY`cannot be run in a transaction block and is not allowed if the partitioned table contains a default partition. If`FINALIZE`is specified, a previous`DETACH CONCURRENTLY`invocation that was canceled or interrupted is completed. At most one partition in a partitioned table can be pending detach at a time. All the forms of ALTER TABLE that act on a single table, except`RENAME`,`SET SCHEMA`,`ATTACH PARTITION`, and`DETACH PARTITION`can be combined into a list of multiple alterations to be applied together. For example, it is possible to add several columns and/or alter the type of several columns in a single command. This is particularly useful with large tables, since only one pass over the table need be made. You must own the table to use`ALTER TABLE`. To change the schema or tablespace of a table, you must also have`CREATE`privilege on the new schema or tablespace. To add the table as a new child of a parent table, you must own the parent table as well. Also, to attach a table as a new partition of the table, you must own the table being attached. To alter the owner, you must also be a direct or indirect member of the new owning role, and that role must have`CREATE`privilege on the table's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the table. However, a superuser can alter ownership of any table anyway.) To add a column or alter a column type or use the`OF`clause, you must also have`USAGE`privilege on the data type. ## Parameters `IF EXISTS` Do not throw an error if the table does not exist. A notice is issued in this case. *`name`* The name (optionally schema-qualified) of an existing table to alter. If`ONLY`is specified before the table name, only that table is altered. If`ONLY`is not specified, the table and all its descendant tables (if any) are altered. Optionally,`*`can be specified after the table name to explicitly indicate that descendant tables are included. *`列名`* 新列或现有列的名称。 *`新列名`* 现有列的新名称。 *`新名字`* 表的新名称。 *`数据类型`* 新列的数据类型,或现有列的新数据类型。 *`表约束`* 表的新表约束。 *`约束名`* 新约束或现有约束的名称。 `级联` 自动删除依赖于已删除列或约束的对象(例如,引用该列的视图),然后依次删除依赖于这些对象的所有对象(请参阅[第 5.14 节](ddl-depend.html))。 `严格` 如果有任何依赖对象,则拒绝删除列或约束。这是默认行为。 *`触发器名称`* 要禁用或启用的单个触发器的名称。 `全部` 禁用或启用属于该表的所有触发器。(如果任何触发器是内部生成的约束触发器,例如用于实现外键约束或可延迟唯一性和排除约束的触发器,则这需要超级用户权限。) `用户` 禁用或启用属于表的所有触发器,内部生成的约束触发器除外,例如用于实现外键约束或可延迟唯一性和排除约束的触发器。 *`索引名称`* 现有索引的名称。 *`存储参数`* 表存储参数的名称。 *`价值`* 表存储参数的新值。这可能是一个数字或一个单词,具体取决于参数。 *`父表`* 要与此表关联或取消关联的父表。 *`新主人`* 表的新所有者的用户名。 *`新表空间`* 表将被移动到的表空间的名称。 *`新模式`* 表将被移动到的模式的名称。 *`分区名`* 要作为新分区附加或从该表分离的表的名称。 *`partition_bound_spec`* 新分区的分区绑定规范。参考[创建表](sql-createtable.html)有关相同语法的更多详细信息。 ## 笔记 关键词`柱子`是噪声,可以省略。 当添加一列时`添加列`和非易失性`默认`如果指定,则在执行语句时评估默认值,并将结果存储在表的元数据中。该值将用于所有现有行的列。如果不`默认`已指定,则使用 NULL。在这两种情况下都不需要重写表。 添加具有 volatile 的列`默认`或更改现有列的类型将需要重写整个表及其索引。作为一个例外,在更改现有列的类型时,如果`使用`子句不会更改列内容,并且旧类型要么是二进制可强制转换为新类型,要么是新类型上的不受约束的域,不需要表重写;但仍必须重建受影响列上的任何索引。对于大型表,表和/或索引重建可能需要大量时间;并且将暂时需要两倍的磁盘空间。 添加一个`查看`要么`非空`约束需要扫描表以验证现有行是否满足约束,但不需要重写表。 类似地,在附加新分区时,可能会对其进行扫描以验证现有行是否满足分区约束。 提供在单个文件中指定多个更改的选项的主要原因`更改表`是多个表扫描或重写可以组合成一个单一的遍历表。 扫描大表以验证新的外键或检查约束可能需要很长时间,并且对表的其他更新被锁定,直到`ALTER TABLE 添加约束`命令已提交。的主要目的`无效`约束选项是减少添加约束对并发更新的影响。和`无效`, 这`添加约束`命令不扫描表,可以立即提交。之后,一个`验证约束`可以发出命令来验证现有行是否满足约束。验证步骤不需要锁定并发更新,因为它知道其他事务将对它们插入或更新的行执行约束;只需要检查预先存在的行。因此,验证只获得一个`共享更新独家`锁定正在更改的表。(如果约束是外键,那么`行共享`约束所引用的表也需要锁。)除了提高并发性之外,使用`无效`和`验证约束`在已知表格包含预先存在的违规行为的情况下。一旦约束到位,就不能插入新的违规行为,并且可以随意纠正现有问题,直到`验证约束`终于成功了。 这`删除列`form 不会物理删除该列,而只是使其对 SQL 操作不可见。表中的后续插入和更新操作将存储该列的空值。因此,删除列很快,但不会立即减少表的磁盘大小,因为被删除列占用的空间不会被回收。随着现有行的更新,空间将随着时间的推移而被回收。 要强制立即回收被丢弃的列占用的空间,您可以执行以下形式之一`更改表`执行整个表的重写。这将导致重建每一行,并将删除的列替换为空值。 重写的形式`更改表`不是 MVCC 安全的。表重写后,如果并发事务使用的是在重写发生之前拍摄的快照,则表将显示为空。看[第 13.5 节](mvcc-caveats.html)更多细节。 这`使用`选项`设置数据类型`实际上可以指定任何涉及该行旧值的表达式;也就是说,它可以引用其他列以及正在转换的列。这允许使用`设置数据类型`句法。由于这种灵活性,`使用`表达式不适用于列的默认值(如果有);结果可能不是默认值所需的常量表达式。这意味着当没有从旧类型到新类型的隐式或赋值转换时,`设置数据类型`可能无法转换默认值,即使`使用`条款提供。在这种情况下,删除默认值`删除默认值`, 执行`改变类型`,然后使用`默认设置`添加合适的新默认值。类似的考虑适用于涉及列的索引和约束。 如果一个表有任何后代表,则不允许在父表中添加、重命名或更改列的类型,而不对后代进行相同的操作。这可确保后代始终具有与父级匹配的列。同样,一个`查看`约束不能在父级中重命名而不在所有后代中重命名,因此`查看`约束条件也在父代与其后代之间匹配。(但是,该限制不适用于基于索引的约束。)此外,由于从父项中选择也从其后代中选择,因此对父项的约束不能标记为有效,除非它也对这些后代标记为有效。在所有这些情况下,`仅更改表`将被拒绝。 递归`删除列`仅当后代不从任何其他父级继承该列并且从未对该列进行独立定义时,操作才会删除后代表的列。非递归的`删除列`(IE。,`仅更改表...删除列`) 从不删除任何后代列,而是将它们标记为独立定义而不是继承。非递归的`删除列`对于分区表,命令将失败,因为表的所有分区必须具有与分区根相同的列。 标识列的操作 (`添加生成`,`放`ETC。,`放弃身份`),以及动作`扳机`,`簇`,`所有者`, 和`表空间`从不递归到后代表;也就是说,他们总是表现得好像`只要`被指定。添加约束仅针对`查看`未标记的约束`没有继承`. 不允许更改系统目录表的任何部分。 参考[创建表](sql-createtable.html)有关有效参数的进一步说明。[第 5 章](ddl.html)有更多关于继承的信息。 ## 例子 添加类型的列`varchar`到一张桌子: ``` ALTER TABLE distributors ADD COLUMN address varchar(30); ``` 这将导致表中的所有现有行都被新列的空值填充。 添加具有非空默认值的列: ``` ALTER TABLE measurements ADD COLUMN mtime timestamp with time zone DEFAULT now(); ``` 现有行将填充当前时间作为新列的值,然后新行将接收其插入时间。 要添加一列并使用与稍后使用的默认值不同的值填充它: ``` ALTER TABLE transactions ADD COLUMN status varchar(30) DEFAULT 'old', ALTER COLUMN status SET default 'current'; ``` 现有行将被填充`老的`,但随后命令的默认值将是`当前的`.效果与两个子命令分别发出一样`更改表`命令。 要从表中删除列: ``` ALTER TABLE distributors DROP COLUMN address RESTRICT; ``` 要在一个操作中更改两个现有列的类型: ``` ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER COLUMN name TYPE varchar(100); ``` 将包含 Unix 时间戳的整数列更改为`带时区的时间戳`通过一个`使用`条款: ``` ALTER TABLE foo ALTER COLUMN foo_timestamp SET DATA TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second'; ``` 同样,当列具有不会自动转换为新数据类型的默认表达式时: ``` ALTER TABLE foo ALTER COLUMN foo_timestamp DROP DEFAULT, ALTER COLUMN foo_timestamp TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second', ALTER COLUMN foo_timestamp SET DEFAULT now(); ``` 要重命名现有列: ``` ALTER TABLE distributors RENAME COLUMN address TO city; ``` 要重命名现有表: ``` ALTER TABLE distributors RENAME TO suppliers; ``` 要重命名现有约束: ``` ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip_check; ``` 向列添加非空约束: ``` ALTER TABLE distributors ALTER COLUMN street SET NOT NULL; ``` 要从列中删除非空约束: ``` ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL; ``` 向表及其所有子表添加检查约束: ``` ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5); ``` 要将检查约束仅添加到表而不添加到其子表: ``` ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT; ``` (未来的孩子也不会继承检查约束。) 要从表及其所有子表中删除检查约束: ``` ALTER TABLE distributors DROP CONSTRAINT zipchk; ``` 仅从一个表中删除检查约束: ``` ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk; ``` (所有子表的检查约束仍然存在。) 向表中添加外键约束: ``` ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address); ``` 将外键约束添加到对其他工作影响最小的表中: ``` ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID; ALTER TABLE distributors VALIDATE CONSTRAINT distfk; ``` 向表中添加(多列)唯一约束: ``` ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode); ``` 要将自动命名的主键约束添加到表中,请注意表只能有一个主键: ``` ALTER TABLE distributors ADD PRIMARY KEY (dist_id); ``` 要将表移动到不同的表空间: ``` ALTER TABLE distributors SET TABLESPACE fasttablespace; ``` 要将表移动到不同的架构: ``` ALTER TABLE myschema.distributors SET SCHEMA yourschema; ``` 要重新创建主键约束,在重建索引时不阻塞更新: ``` CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id); ALTER TABLE distributors DROP CONSTRAINT distributors_pkey, ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx; ``` 要将分区附加到范围分区表: ``` ALTER TABLE measurement ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); ``` 要将分区附加到列表分区表: ``` ALTER TABLE cities ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b'); ``` 要将分区附加到散列分区表: ``` ALTER TABLE orders ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3); ``` 要将默认分区附加到分区表: ``` ALTER TABLE cities ATTACH PARTITION cities_partdef DEFAULT; ``` 要从分区表中分离分区: ``` ALTER TABLE measurement DETACH PARTITION measurement_y2015m12; ``` ## 兼容性 表格`添加`(没有`使用索引`),`删除 [栏]`,`放弃身份`,`重新开始`,`默认设置`,`设置数据类型`(没有`使用`),`集生成`, 和`放 *`序列选项`*`符合 SQL 标准。其他形式是 SQL 标准的 PostgreSQL 扩展。此外,能够在单个操作中指定多个操作`更改表`命令是一个扩展。 `更改表删除列`可用于删除表的唯一列,留下一个零列表。这是 SQL 的扩展,它不允许零列表。 ## 也可以看看 [创建表](sql-createtable.html)