# 更改表

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 } ]

# 描述

更改表更改现有表的定义。下面描述了几个子窗体。请注意,每个子表单所需的锁定级别可能不同。一个访问独家除非明确说明,否则会获取锁。当给出多个子命令时,获得的锁将是任何子命令所需的最严格的锁。

添加列 [如果不存在]

此表单使用与以下相同的语法向表中添加一个新列创建表.如果如果不存在已指定且已存在具有此名称的列,则不会引发错误。

删除列 [如果存在]

此表单从表中删除一列。涉及该列的索引和表约束也将被自动删除。如果删除列会导致统计信息仅包含单个列的数据,则引用已删除列的多变量统计信息也将被删除。你需要说级联如果表之外的任何内容取决于列,例如外键引用或视图。如果如果存在指定并且该列不存在,则不会引发错误。在这种情况下,将发出通知。

设置数据类型

此表单更改表格列的类型。通过重新解析最初提供的表达式,涉及该列的索引和简单表约束将自动转换为使用新的列类型。可选的整理子句指定新列的排序规则;如果省略,则排序规则是新列类型的默认值。可选的使用子句指定如何从旧列值计算新列值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。一种使用如果没有从旧类型到新类型的隐式或赋值强制转换,则必须提供子句。

/删除默认值

这些表单设置或删除列的默认值(其中删除相当于将默认值设置为 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.

IfDROP EXPRESSION IF EXISTSis 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. SeeCREATE TABLEfor details. LikeSET DEFAULT, these forms only affect the behavior of subsequentINSERTandUPDATEcommands; they do not cause rows already in the table to change.

IfDROP IDENTITY IF EXISTSis 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 byALTER SEQUENCEsuch as增量.

设置统计

这种形式为后续的每列统计收集目标设置分析操作。目标可在 0 到 10000 范围内设置;或者,将其设置为 -1 以恢复使用系统默认统计目标 (默认_统计数据_目标)。有关 PostgreSQL 查询计划器使用统计信息的更多信息,请参阅第 14.2 节.

设置统计获得一个共享更新独家锁。

放 ( *属性选项* = *价值* [, ... ] )
重置 ( *属性选项* [, ... ] )

此表单设置或重置每个属性选项。目前,唯一定义的每个属性选项是n_distinctn_distinct_inherited,它覆盖了后续所做的不同值的数量估计分析操作。n_distinct影响表本身的统计信息,而n_distinct_inherited影响为表及其继承子级收集的统计信息。当设置为正值时,分析将假定该列正好包含指定数量的不同非空值。当设置为负值时,必须大于或等于 -1,分析将假设列中不同的非空值的数量与表的大小成线性关系;确切的计数是通过将估计的表大小乘以给定数字的绝对值来计算的。例如,值 -1 意味着列中的所有值都是不同的,而值 -0.5 意味着每个值平均出现两次。当表的大小随时间变化时,这可能很有用,因为直到查询计划时间才执行乘以表中的行数。指定值 0 以恢复正常估计不同值的数量。有关 PostgreSQL 查询计划器使用统计信息的更多信息,请参阅第 14.2 节.

更改每个属性选项会获得共享更新独家锁。

设置存储

此表单设置列的存储模式。这控制此列是内联保存还是保存在辅助 TOAST 表中,以及是否应压缩数据。清楚的必须用于固定长度的值,例如整数并且是内联的,未压缩的。主要的用于内联的可压缩数据。外部的用于外部未压缩数据,并且扩展用于外部压缩数据。扩展是大多数支持非清楚的贮存。用于外部的将使子字符串操作非常大文本拜茶值运行得更快,但会增加存储空间。注意设置存储它本身不会改变表格中的任何内容,它只是设置在未来表格更新期间要采用的策略。看第 70.2 节了解更多信息。

设置压缩 *压缩方法*

此表单设置列的压缩方法,确定将来插入的值将如何压缩(如果存储模式完全允许压缩)。这不会导致表被重写,因此现有数据仍可能使用其他压缩方法进行压缩。如果表是用 pg 恢复的_恢复,然后使用配置的压缩方法重写所有值。但是,当从另一个关系插入数据时(例如,通过插入...选择),源表中的值不一定会被解压,因此任何先前压缩的数据都可能保留其现有的压缩方法,而不是使用目标列的压缩方法重新压缩。支持的压缩方法是pglzlz4.(lz4仅在以下情况下可用--with-lz4在构建 PostgreSQL 时使用。)此外,*压缩方法*可default, which selects the default behavior of consulting thedefault_toast_compressionsetting 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 asCREATE TABLE, plus the optionNOT 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 theNOT VALIDoption 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 theVALIDATE CONSTRAINToption. SeeNotesbelow for more information about using theNOT VALIDoption.

Although most forms ofADD *table_constraint*require an访问独家锁,添加外键只需要一个共享行独家锁。注意添加外键还获得了一个共享行独家除了在声明约束的表上锁定之外,还锁定被引用的表。

将唯一键或主键约束添加到分区表时会应用其他限制;看创建表.此外,可能不会声明分区表上的外键约束无效目前。

添加 *table_constraint_using_index*

这种形式增加了一个新的首要的关键要么独特基于现有唯一索引的表的约束。索引的所有列都将包含在约束中。

索引不能有表达式列,也不能是部分索引。此外,它必须是具有默认排序顺序的 b 树索引。这些限制确保索引等同于由常规构建的索引添加主键要么添加唯一命令。

如果首要的关键已指定,并且索引的列尚未标记非空, 那么这个命令会尝试做ALTER COLUMN SET NOT NULL针对每个这样的列。这需要全表扫描来验证列不包含空值。在所有其他情况下,这是一个快速操作。

如果提供了约束名称,则索引将被重命名以匹配约束名称。否则,约束将被命名为与索引相同。

执行此命令后,索引由约束“拥有”,就像索引已由常规构建一样添加主键要么添加唯一命令。特别是,删除约束也会使索引消失。

分区表目前不支持这种形式。

# 笔记

在需要添加新约束而又不长时间阻塞表更新的情况下,使用现有索引添加约束可能会很有帮助。为此,请使用创建索引并发创建索引,然后使用此语法将其安装为官方约束。请参见下面的示例。

改变约束

这种形式改变了先前创建的约束的属性。目前只有外键约束可以改变。

验证约束

此表单验证先前创建为的外键或检查约束无效,通过扫描表以确保没有不满足约束的行。如果约束已被标记为有效,则不会发生任何事情。(看笔记下面解释了这个命令的用处。)

该命令获取一个共享更新独家锁。

删除约束 [如果存在]

此表单删除表上的指定约束以及约束下的任何索引。如果如果存在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 variablesession_replication_role. Simply enabled triggers (the default) will fire when the replication role is “origin” (the default) or “local”. Triggers configured asENABLE REPLICAwill only fire if the session is in “replica” mode, and triggers configured asENABLE ALWAYSwill 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 toENABLE ALWAYSso that it is also fired on replicas.

This command acquires aSHARE ROW EXCLUSIVElock.

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 forON SELECTrules, 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 variablesession_复制_角色,类似于上面描述的触发器。

禁用/启用行级安全

这些表单控制属于表的行安全策略的应用。如果已启用且表不存在任何策略,则应用默认拒绝策略。请注意,即使禁用了行级安全性,表也可以存在策略。在这种情况下,政策将不是被应用并且策略将被忽略。也可以看看创建政策.

没有力量/强制行级安全

当用户是表所有者时,这些表单控制属于表的行安全策略的应用。如果启用,当用户是表所有者时将应用行级安全策略。如果禁用(默认),则当用户是表所有者时,不会应用行级安全性。也可以看看创建政策.

集群开启

此表单选择未来的默认索引操作。它实际上并没有重新聚集表。

更改集群选项会获得共享更新独家锁。

无簇集

此表单删除最近使用的表中的索引规范。这会影响未指定索引的未来集群操作。

更改集群选项会获得共享更新独家锁。

无 OID 设置

用于删除的向后兼容语法样的系统栏。作为样的无法再添加系统列,这永远不会产生影响。

设置表空间

此表单将表的表空间更改为指定的表空间,并将与表关联的数据文件移动到新的表空间。表上的索引(如果有)不会移动;但它们可以单独移动设置表空间命令。当应用于分区表时,不会移动任何内容,但之后创建的任何分区创建表分区将使用该表空间,除非被表空间条款。

表空间中当前数据库中的所有表都可以使用全部在表空间中表单,它将先锁定所有要移动的表,然后再移动每个表。这种形式还支持拥有者,这只会移动指定角色拥有的表。如果现在等待如果指定了选项,则如果无法立即获取所需的所有锁,该命令将失败。请注意,此命令不会移动系统目录;采用更改数据库或明确的更改表如果需要,可以调用。这信息模式关系不被视为系统目录的一部分,将被移动。也可以看看CREATE TABLESPACE.

SET { LOGGED | UNLOGGED }

This form changes the table from unlogged to logged or vice-versa (seeUNLOGGED). It cannot be applied to a temporary table.

SET ( *storage_parameter* [= *value*] [, ... ] )

This form changes one or more storage parameters for the table. SeeStorage Parametersin theCREATE TABLEdocumentation 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 withVACUUM FULL,CLUSTERor one of the forms ofALTER TABLEthat 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 EXCLUSIVElock will be taken for fillfactor, toast and autovacuum storage parameters, as well as the planner parameterparallel_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 usingFOR VALUESor as a default partition by usingDEFAULT. 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 ifALTER INDEX ATTACH PARTITIONhad 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 areUNIQUEindexes on the target table. (See alsoCREATE FOREIGN TABLE.) For each user-defined row-level trigger that exists in the target table, a corresponding one is created in the attached table.

A partition usingFOR VALUESuses same syntax for*partition_bound_spec*asCREATE TABLE. 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 theNOT NULLandCHECKconstraints of the target table. CurrentlyFOREIGN KEYconstraints are not considered.UNIQUEand首要的关键如果父表中的约束不存在,则将在分区中创建它们。如果任何一个查看被附加的表的约束被标记没有继承,命令将失败;必须在没有没有继承条款。

如果新分区是常规表,则执行全表扫描以检查表中的现有行是否违反分区约束。可以通过添加一个有效的查看对表的约束,在运行此命令之前只允许满足所需分区约束的行。这查看约束将用于确定不需要扫描表来验证分区约束。但是,如果任何分区键是表达式并且分区不接受,则这不起作用空值价值观。如果附加一个不接受的列表分区空值值,还添加非空对分区键列的约束,除非它是一个表达式。

如果新分区是外表,则不做任何事情来验证外表中的所有行是否符合分区约束。(见讨论创建外表关于外表的约束。)

当表具有默认分区时,定义新分区会更改默认分区的分区约束。默认分区不能包含任何需要移动到新分区的行,并且将被扫描以验证是否不存在任何行。这种扫描,就像对新分区的扫描一样,如果适当的话可以避免查看存在约束。也和新分区的扫描一样,默认分区是外表时总是跳过。

附加一个分区会获得一个共享更新独家锁定父表,除了访问独家锁定正在附加的表和默认分区(如果有)。

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 aCHECKconstraint as described inSection 5.11.2.2.

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.SHARElock is obtained on any tables that reference this partitioned table in foreign key constraints.

IfCONCURRENTLYis 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, aSHARE UPDATE EXCLUSIVElock 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 acquiresSHARE UPDATE EXCLUSIVEon the partitioned table andACCESS EXCLUSIVEon the partition, and the detach process completes. ACHECKconstraint that duplicates the partition constraint is added to the partition.CONCURRENTLYcannot be run in a transaction block and is not allowed if the partitioned table contains a default partition.

IfFINALIZEis specified, a previousDETACH CONCURRENTLYinvocation 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, exceptRENAME,SET SCHEMA,ATTACH PARTITION, andDETACH PARTITIONcan 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 useALTER TABLE. To change the schema or tablespace of a table, you must also haveCREATEprivilege 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 haveCREATEprivilege 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 theOFclause, you must also haveUSAGEprivilege 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. IfONLYis specified before the table name, only that table is altered. IfONLYis 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 节)。

严格

如果有任何依赖对象,则拒绝删除列或约束。这是默认行为。

触发器名称

要禁用或启用的单个触发器的名称。

全部

禁用或启用属于该表的所有触发器。(如果任何触发器是内部生成的约束触发器,例如用于实现外键约束或可延迟唯一性和排除约束的触发器,则这需要超级用户权限。)

用户

禁用或启用属于表的所有触发器,内部生成的约束触发器除外,例如用于实现外键约束或可延迟唯一性和排除约束的触发器。

索引名称

现有索引的名称。

存储参数

表存储参数的名称。

价值

表存储参数的新值。这可能是一个数字或一个单词,具体取决于参数。

父表

要与此表关联或取消关联的父表。

新主人

表的新所有者的用户名。

新表空间

表将被移动到的表空间的名称。

新模式

表将被移动到的模式的名称。

分区名

要作为新分区附加或从该表分离的表的名称。

partition_bound_spec

新分区的分区绑定规范。参考创建表有关相同语法的更多详细信息。

# 笔记

关键词柱子是噪声,可以省略。

当添加一列时添加列和非易失性默认如果指定,则在执行语句时评估默认值,并将结果存储在表的元数据中。该值将用于所有现有行的列。如果不默认已指定,则使用 NULL。在这两种情况下都不需要重写表。

添加具有 volatile 的列默认或更改现有列的类型将需要重写整个表及其索引。作为一个例外,在更改现有列的类型时,如果使用子句不会更改列内容,并且旧类型要么是二进制可强制转换为新类型,要么是新类型上的不受约束的域,不需要表重写;但仍必须重建受影响列上的任何索引。对于大型表,表和/或索引重建可能需要大量时间;并且将暂时需要两倍的磁盘空间。

添加一个查看要么非空约束需要扫描表以验证现有行是否满足约束,但不需要重写表。

类似地,在附加新分区时,可能会对其进行扫描以验证现有行是否满足分区约束。

提供在单个文件中指定多个更改的选项的主要原因更改表是多个表扫描或重写可以组合成一个单一的遍历表。

扫描大表以验证新的外键或检查约束可能需要很长时间,并且对表的其他更新被锁定,直到ALTER TABLE 添加约束命令已提交。的主要目的无效约束选项是减少添加约束对并发更新的影响。和无效, 这添加约束命令不扫描表,可以立即提交。之后,一个验证约束可以发出命令来验证现有行是否满足约束。验证步骤不需要锁定并发更新,因为它知道其他事务将对它们插入或更新的行执行约束;只需要检查预先存在的行。因此,验证只获得一个共享更新独家锁定正在更改的表。(如果约束是外键,那么行共享约束所引用的表也需要锁。)除了提高并发性之外,使用无效验证约束在已知表格包含预先存在的违规行为的情况下。一旦约束到位,就不能插入新的违规行为,并且可以随意纠正现有问题,直到验证约束终于成功了。

删除列form 不会物理删除该列,而只是使其对 SQL 操作不可见。表中的后续插入和更新操作将存储该列的空值。因此,删除列很快,但不会立即减少表的磁盘大小,因为被删除列占用的空间不会被回收。随着现有行的更新,空间将随着时间的推移而被回收。

要强制立即回收被丢弃的列占用的空间,您可以执行以下形式之一更改表执行整个表的重写。这将导致重建每一行,并将删除的列替换为空值。

重写的形式更改表不是 MVCC 安全的。表重写后,如果并发事务使用的是在重写发生之前拍摄的快照,则表将显示为空。看第 13.5 节更多细节。

使用选项设置数据类型实际上可以指定任何涉及该行旧值的表达式;也就是说,它可以引用其他列以及正在转换的列。这允许使用设置数据类型句法。由于这种灵活性,使用表达式不适用于列的默认值(如果有);结果可能不是默认值所需的常量表达式。这意味着当没有从旧类型到新类型的隐式或赋值转换时,设置数据类型可能无法转换默认值,即使使用条款提供。在这种情况下,删除默认值删除默认值, 执行改变类型,然后使用默认设置添加合适的新默认值。类似的考虑适用于涉及列的索引和约束。

如果一个表有任何后代表,则不允许在父表中添加、重命名或更改列的类型,而不对后代进行相同的操作。这可确保后代始终具有与父级匹配的列。同样,一个查看约束不能在父级中重命名而不在所有后代中重命名,因此查看约束条件也在父代与其后代之间匹配。(但是,该限制不适用于基于索引的约束。)此外,由于从父项中选择也从其后代中选择,因此对父项的约束不能标记为有效,除非它也对这些后代标记为有效。在所有这些情况下,仅更改表将被拒绝。

递归删除列仅当后代不从任何其他父级继承该列并且从未对该列进行独立定义时,操作才会删除后代表的列。非递归的删除列(IE。,仅更改表...删除列) 从不删除任何后代列,而是将它们标记为独立定义而不是继承。非递归的删除列对于分区表,命令将失败,因为表的所有分区必须具有与分区根相同的列。

标识列的操作 (添加生成,ETC。,放弃身份),以及动作扳机,,所有者, 和表空间从不递归到后代表;也就是说,他们总是表现得好像只要被指定。添加约束仅针对查看未标记的约束没有继承.

不允许更改系统目录表的任何部分。

参考创建表有关有效参数的进一步说明。第 5 章有更多关于继承的信息。

# 例子

添加类型的列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 的扩展,它不允许零列表。

# 也可以看看

创建表