支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

ALTER TABLE

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 SET EXPRESSION AS ( expression )
    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 | DEFAULT }
    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 | DEFAULT }
    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 ACCESS METHOD { new_access_method | DEFAULT }
    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 [ NULLS [ NOT ] DISTINCT ] 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 [ NULLS [ NOT ] DISTINCT ] ( 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 ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

referential_action in a FOREIGN KEY/REFERENCES constraint is:

{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }

描述

ALTER TABLE 更改现有表的定义。下面描述了几种子形式。请注意,每种子形式所需的锁级别可能不同。除非明确指出,否则将获取 ACCESS EXCLUSIVE 锁。当给出多个子命令时,获取的锁将是任何子命令所需的最严格的锁。

ADD COLUMN [ IF NOT EXISTS ] #

此形式使用与 CREATE TABLE 相同的语法向表中添加新列。如果指定了 IF NOT EXISTS 并且已存在具有此名称的列,则不会引发错误。

DROP COLUMN [ IF EXISTS ] #

此形式从表中删除列。涉及该列的索引和表约束也将自动删除。如果删除该列会导致统计信息仅包含单个列的数据,则还会删除引用已删除列的多元统计信息。如果表之外的任何内容依赖于该列,例如外键引用或视图,则需要使用 CASCADE。如果指定了 IF EXISTS 并且该列不存在,则不会引发错误。在这种情况下,会发出通知。

SET DATA TYPE #

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

使用此形式时,将删除列的统计信息,因此建议之后对表运行 ANALYZE

SET/DROP DEFAULT #

这些形式设置或删除列的默认值(其中删除等效于将默认值设置为 NULL)。新的默认值仅适用于后续的 INSERTUPDATE 命令;它不会导致表中已有的行发生更改。

SET/DROP NOT NULL #

这些形式更改列是否标记为允许空值或拒绝空值。

SET NOT NULL 只能应用于表中没有记录包含该列的 NULL 值的列。通常,这会在 ALTER TABLE 期间通过扫描整个表进行检查;但是,如果找到有效的 CHECK 约束证明不存在 NULL,则会跳过表扫描。

如果此表是分区,则如果父表中将列标记为 NOT NULL,则无法对该列执行 DROP NOT NULL。要从所有分区中删除 NOT NULL 约束,请对父表执行 DROP NOT NULL。即使父级上没有 NOT NULL 约束,如果需要,仍然可以将这样的约束添加到各个分区;也就是说,子级可以禁止空值,即使父级允许它们,但反之则不然。

SET EXPRESSION AS #

此形式替换生成列的表达式。列中的现有数据会被重写,并且所有将来的更改都将应用新的生成表达式。

DROP EXPRESSION [ IF EXISTS ] #

此形式将存储的生成列转换为普通的基本列。列中的现有数据会保留,但将来的更改将不再应用生成表达式。

如果指定了 DROP EXPRESSION IF EXISTS 并且该列不是存储的生成列,则不会引发错误。在这种情况下,会发出通知。

ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
SET GENERATED { ALWAYS | BY DEFAULT }
DROP IDENTITY [ IF EXISTS ] #

这些形式更改列是否为标识列,或更改现有标识列的生成属性。有关详细信息,请参阅 CREATE TABLE。与 SET DEFAULT 一样,这些形式仅影响后续 INSERTUPDATE 命令的行为;它们不会导致表中已有的行发生更改。

如果指定了 DROP IDENTITY IF EXISTS 并且该列不是标识列,则不会引发错误。在这种情况下,会发出通知。

SET sequence_option
RESTART #

这些形式更改现有标识列的基础序列。sequence_optionALTER SEQUENCE 支持的选项,例如 INCREMENT BY

SET STATISTICS #

此形式为后续 ANALYZE 操作设置每个列的统计信息收集目标。目标可以在 0 到 10000 的范围内设置。将其设置为 DEFAULT 可恢复为使用系统默认统计信息目标 (default_statistics_target)。(设置为 -1 的值是一种过时的方式来获得相同的结果。)有关 PostgreSQL 查询规划器使用统计信息的更多信息,请参阅 第 14.2 节

SET STATISTICS 获取 SHARE UPDATE EXCLUSIVE 锁。

SET ( attribute_option = value [, ... ] )
RESET ( attribute_option [, ... ] ) #

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

更改每个属性的选项会获取一个 SHARE UPDATE EXCLUSIVE 锁。

SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } #

此表单设置列的存储模式。这将控制此列是内联保存还是在辅助TOAST表中保存,以及数据是否应压缩。PLAIN 必须用于固定长度的值,例如 integer,并且是内联的、未压缩的。MAIN 用于内联的、可压缩的数据。EXTERNAL 用于外部的、未压缩的数据,而 EXTENDED 用于外部的、压缩的数据。编写 DEFAULT 会将存储模式设置为列数据类型的默认模式。EXTENDED 是大多数支持非 PLAIN 存储的数据类型的默认值。使用 EXTERNAL 将使对非常大的 textbytea 值进行子字符串操作的速度更快,但会增加存储空间。请注意,ALTER TABLE ... SET STORAGE 本身不会更改表中的任何内容;它只是设置在未来表更新期间要遵循的策略。有关更多信息,请参阅 第 65.2 节

SET COMPRESSION compression_method #

此表单设置列的压缩方法,确定未来插入的值将如何压缩(如果存储模式允许压缩)。这不会导致表被重写,因此现有数据可能仍然使用其他压缩方法进行压缩。如果使用 pg_restore 还原表,则所有值都将使用配置的压缩方法重写。但是,当从另一个关系中插入数据时(例如,通过 INSERT ... SELECT),来自源表的值不一定会被解包,因此任何以前压缩的数据可能会保留其现有的压缩方法,而不是使用目标列的压缩方法重新压缩。支持的压缩方法是 pglzlz4。(只有在构建 PostgreSQL 时使用了 --with-lz4lz4 才可用。)此外,compression_method 可以是 default,它会选择在数据插入时咨询 default_toast_compression 设置的默认行为,以确定要使用的方法。

ADD table_constraint [ NOT VALID ] #

此表单使用与 CREATE TABLE 相同的约束语法向表中添加新约束,以及选项 NOT VALID,该选项目前仅允许用于外键和 CHECK 约束。

通常,此表单会导致扫描表以验证表中所有现有行是否满足新约束。但是,如果使用 NOT VALID 选项,则会跳过此潜在的耗时扫描。该约束仍将针对后续插入或更新强制执行(也就是说,如果在外键的情况下引用的表中没有匹配的行,它们将失败;或者,如果新行与指定的检查条件不匹配,它们将失败)。但是,除非使用 VALIDATE CONSTRAINT 选项进行验证,否则数据库不会假定该约束对表中的所有行都成立。有关使用 NOT VALID 选项的更多信息,请参阅下面的注释

尽管大多数形式的 ADD table_constraint 都需要 ACCESS EXCLUSIVE 锁,但 ADD FOREIGN KEY 只需要 SHARE ROW EXCLUSIVE 锁。请注意,ADD FOREIGN KEY 除了在声明约束的表上加锁外,还会在被引用的表上获取一个 SHARE ROW EXCLUSIVE 锁。

当向分区表添加唯一约束或主键约束时,会应用其他限制;请参阅 CREATE TABLE。此外,目前分区表上的外键约束不能声明为 NOT VALID

ADD table_constraint_using_index #

此表单基于现有的唯一索引向表中添加新的 PRIMARY KEYUNIQUE 约束。索引的所有列都将包含在约束中。

索引不能有表达式列,也不能是部分索引。此外,它必须是具有默认排序顺序的 b 树索引。这些限制确保索引等同于由常规的 ADD PRIMARY KEYADD UNIQUE 命令构建的索引。

如果指定了 PRIMARY KEY,并且索引的列尚未标记为 NOT NULL,则此命令将尝试对每个这样的列执行 ALTER COLUMN SET NOT NULL。这需要进行完整的表扫描以验证列是否不包含任何 null 值。在所有其他情况下,这是一个快速操作。

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

执行此命令后,索引将由约束“拥有”,就像索引是由常规的 ADD PRIMARY KEYADD UNIQUE 命令构建的一样。特别是,删除约束也会使索引消失。

当前,分区表不支持此表单。

注意

在需要添加新约束而不会长时间阻止表更新的情况下,使用现有索引添加约束会很有帮助。为此,请使用 CREATE UNIQUE INDEX CONCURRENTLY 创建索引,然后使用此语法将其转换为约束。请参阅下面的示例。

ALTER CONSTRAINT #

此表单更改先前创建的约束的属性。目前,只能更改外键约束。

VALIDATE CONSTRAINT #

此表单验证先前创建为 NOT VALID 的外键或检查约束,方法是扫描表以确保没有不满足约束的行。如果约束已标记为有效,则不会发生任何事情。(有关此命令有用性的说明,请参阅下面的 注释。)

此命令获取 SHARE UPDATE EXCLUSIVE 锁。

DROP CONSTRAINT [ IF EXISTS ] #

此表单删除表上指定的约束,以及约束下的任何索引。如果指定了 IF EXISTS 并且约束不存在,则不会引发错误。在这种情况下,会发出一个通知。

DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER #

这些表单配置属于该表的触发器的触发。禁用的触发器仍然为系统所知,但在其触发事件发生时不会执行。(对于延迟的触发器,启用状态会在事件发生时检查,而不是在实际执行触发函数时检查。)可以禁用或启用由名称指定的单个触发器,或者表上的所有触发器,或者仅用户触发器(此选项排除内部生成的约束触发器,例如用于实现外键约束或可延迟的唯一性和排除约束的触发器)。禁用或启用内部生成的约束触发器需要超级用户权限;应该谨慎操作,因为如果触发器未执行,当然不能保证约束的完整性。

触发器触发机制还受配置变量 session_replication_role 的影响。简单启用的触发器(默认值)将在复制角色为“origin”(默认值)或“local”时触发。配置为 ENABLE REPLICA 的触发器仅在会话处于“replica”模式时触发,而配置为 ENABLE ALWAYS 的触发器无论当前的复制角色如何都会触发。

此机制的效果是,在默认配置中,触发器不会在副本上触发。这很有用,因为如果使用触发器在源上在表之间传播数据,则复制系统也会复制传播的数据;因此,触发器不应在副本上第二次触发,因为这会导致重复。但是,如果触发器用于其他目的,例如创建外部警报,则可以将其设置为 ENABLE ALWAYS,以便它也在副本上触发。

当此命令应用于分区表时,除非指定了 ONLY,否则还会更新分区中相应克隆触发器的状态。

此命令获取一个 SHARE ROW EXCLUSIVE 锁。

DISABLE/ENABLE [ REPLICA | ALWAYS ] RULE #

这些形式配置属于表的重写规则的触发。禁用的规则系统仍然知道,但在查询重写期间不会应用。其语义与禁用/启用触发器相同。此配置对于 ON SELECT 规则将被忽略,这些规则始终会被应用,以保持视图正常工作,即使当前会话处于非默认复制角色。

规则触发机制也受配置变量 session_replication_role 的影响,类似于上述的触发器。

DISABLE/ENABLE ROW LEVEL SECURITY #

这些形式控制应用于表的行安全策略。如果启用并且该表不存在任何策略,则会应用默认的拒绝策略。请注意,即使禁用行级安全性,表也可以存在策略。在这种情况下,这些策略将不会被应用,并且策略将被忽略。另请参见 CREATE POLICY

NO FORCE/FORCE ROW LEVEL SECURITY #

这些形式控制当用户为表所有者时,应用于表的行安全策略的应用。如果启用,则当用户为表所有者时,将应用行级安全策略。如果禁用(默认),则当用户为表所有者时,将不应用行级安全策略。另请参见 CREATE POLICY

CLUSTER ON #

此形式为将来的 CLUSTER 操作选择默认索引。它实际上不会重新聚集表。

更改聚集选项会获得一个 SHARE UPDATE EXCLUSIVE 锁。

SET WITHOUT CLUSTER #

此形式从表中删除最近使用的 CLUSTER 索引规范。这将影响未来未指定索引的聚集操作。

更改聚集选项会获得一个 SHARE UPDATE EXCLUSIVE 锁。

SET WITHOUT OIDS #

用于删除 oid 系统列的向后兼容语法。由于 oid 系统列不能再添加,这永远不会产生效果。

SET ACCESS METHOD #

此形式通过使用指示的访问方法重写表来更改表的访问方法;指定 DEFAULT 选择设置为 default_table_access_method 配置参数的访问方法。有关更多信息,请参见 第 61 章

当应用于分区表时,没有要重写的数据,但是之后创建的分区将默认为给定的访问方法,除非被 USING 子句覆盖。指定 DEFAULT 将删除先前的值,导致未来的分区默认为 default_table_access_method

SET TABLESPACE #

此形式将表的表空间更改为指定的表空间,并将与该表相关联的数据文件移动到新的表空间。该表上的索引(如果有)不会移动;但是可以使用其他 SET TABLESPACE 命令单独移动它们。当应用于分区表时,不会移动任何内容,但是之后使用 CREATE TABLE PARTITION OF 创建的任何分区都将使用该表空间,除非被 TABLESPACE 子句覆盖。

可以使用 ALL IN TABLESPACE 形式移动表空间中当前数据库中的所有表,这将首先锁定所有要移动的表,然后移动每个表。此形式还支持 OWNED BY,它将仅移动由指定的角色拥有的表。如果指定了 NOWAIT 选项,则如果该命令无法立即获取所有需要的锁,则该命令将失败。请注意,此命令不会移动系统目录;如果需要,请改用 ALTER DATABASE 或显式的 ALTER TABLE 调用。information_schema 关系不被认为是系统目录的一部分,将被移动。另请参见 CREATE TABLESPACE

SET { LOGGED | UNLOGGED } #

此形式将表从非日志记录更改为日志记录,反之亦然(请参见 UNLOGGED)。它不能应用于临时表。

这也更改与表关联的任何序列(对于标识或序列列)的持久性。但是,也可以单独更改此类序列的持久性。

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

此形式更改表的一个或多个存储参数。有关可用参数的详细信息,请参见 CREATE TABLE 文档中的 存储参数。请注意,此命令不会立即修改表内容;根据参数的不同,您可能需要重写表才能获得所需的效果。可以使用 VACUUM FULLCLUSTER 或强制表重写的 ALTER TABLE 的形式之一来完成。对于与计划器相关的参数,更改将从下次锁定表时生效,因此当前执行的查询将不会受到影响。

将为 fillfactor、toast 和 autovacuum 存储参数以及计划器参数 parallel_workers 获取 SHARE UPDATE EXCLUSIVE 锁。

RESET ( storage_parameter [, ... ] ) #

此形式将一个或多个存储参数重置为其默认值。与 SET 一样,可能需要重写表才能完全更新表。

INHERIT parent_table #

此形式将目标表添加为指定父表的新子表。随后,针对父表的查询将包括目标表的记录。要作为子表添加,目标表必须已经包含与父表相同的所有列(它也可以有其他列)。这些列必须具有匹配的数据类型,并且如果它们在父表中具有 NOT NULL 约束,则它们在子表中也必须具有 NOT NULL 约束。

对于父表的所有 CHECK 约束,还必须存在匹配的子表约束,除了那些标记为不可继承的约束(即,使用 ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT 在父表中创建的约束),这些约束将被忽略;所有匹配的子表约束都不能标记为不可继承。当前不考虑 UNIQUEPRIMARY KEYFOREIGN KEY 约束,但这将来可能会改变。

NO INHERIT parent_table #

此形式将目标表从指定父表的子列表删除。针对父表的查询将不再包括从目标表提取的记录。

OF type_name #

此形式将表链接到复合类型,就像 CREATE TABLE OF 形成它一样。表的列名和类型列表必须与复合类型的列名和类型列表精确匹配。该表不得从任何其他表继承。这些限制确保 CREATE TABLE OF 将允许等效的表定义。

NOT OF #

此形式将类型化表与其类型分离。

OWNER TO #

此形式将表、序列、视图、物化视图或外部表的所有者更改为指定的用户。

REPLICA IDENTITY #

此形式更改写入预写日志的信息,以标识已更新或删除的行。在大多数情况下,仅当每一列的旧值与新值不同时才会记录旧值;但是,如果旧值存储在外部,则无论是否更改,都会始终记录旧值。仅当使用逻辑复制时,此选项才有效。

DEFAULT #

记录主键列的旧值(如果有)。这是非系统表的默认设置。

USING INDEX index_name #

记录由命名索引覆盖的列的旧值,该索引必须是唯一的,不能是部分的,不能是可延迟的,并且只能包含标记为 NOT NULL 的列。如果此索引被删除,则行为与 NOTHING 相同。

FULL #

记录行中所有列的旧值。

NOTHING #

不记录有关旧行的任何信息。这是系统表的默认设置。

RENAME #

RENAME 形式更改表(或索引、序列、视图、物化视图或外部表)的名称、表中单个列的名称或表的约束的名称。当重命名具有基础索引的约束时,索引也会被重命名。存储的数据不受影响。

SET SCHEMA #

此形式将表移动到另一个模式。与表列关联的索引、约束和序列也会被移动。

ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } #

此形式将现有表(本身可能已分区)作为目标表的分区附加。该表可以使用 FOR VALUES 作为特定值的分区附加,或者使用 DEFAULT 作为默认分区附加。对于目标表中的每个索引,将在附加表中创建一个对应的索引;或者,如果已存在等效索引,则会将其附加到目标表的索引,就像执行了 ALTER INDEX ATTACH PARTITION 一样。请注意,如果现有表是外部表,则如果目标表上存在 UNIQUE 索引,则当前不允许将该表附加为目标表的分区。(另请参阅 CREATE FOREIGN TABLE。)对于目标表中存在的每个用户定义的行级触发器,将在附加表中创建一个对应的触发器。

使用 FOR VALUES 的分区使用与 CREATE TABLE 相同的 partition_bound_spec 语法。分区边界规范必须与目标表的分区策略和分区键相对应。要附加的表必须具有与目标表相同的所有列,且不能多于;此外,列类型也必须匹配。此外,它必须具有目标表的所有 NOT NULLCHECK 约束,且未标记为 NO INHERIT。目前,不考虑 FOREIGN KEY 约束。如果父表中不存在 UNIQUEPRIMARY KEY 约束,则会在分区中创建这些约束。

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

如果新分区是外部表,则不会执行任何操作来验证外部表中的所有行是否遵守分区约束。(请参阅 CREATE FOREIGN TABLE 中关于外部表约束的讨论。)

当表具有默认分区时,定义新分区会更改默认分区分区约束。默认分区不能包含任何需要移动到新分区的行,并且会扫描以验证是否不存在任何此类行。如果存在适当的 CHECK 约束,则可以避免此扫描,就像新分区的扫描一样。同样,当默认分区是外部表时,始终会跳过此扫描。

附加分区会在父表上获取 SHARE UPDATE EXCLUSIVE 锁,此外还在要附加的表和默认分区(如果有)上获取 ACCESS EXCLUSIVE 锁。

如果要附加的表本身是分区表,则还必须在所有子分区上持有进一步的锁。同样,如果默认分区本身是分区表。可以通过添加 第 5.12.2.2 节中所述的 CHECK 约束来避免子分区的锁定。

DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ] #

此形式分离目标表的指定分区。分离的分区继续作为独立的表存在,但不再与从中分离的表有任何联系。附加到目标表索引的任何索引都会分离。作为目标表中的克隆创建的任何触发器都会被删除。在任何以外键约束引用此分区表的表上获取 SHARE 锁。

如果指定 CONCURRENTLY,则它使用降低的锁级别运行,以避免阻止可能正在访问分区表的其他会话。在此模式下,内部使用两个事务。在第一个事务期间,在父表和分区上都采用 SHARE UPDATE EXCLUSIVE 锁,并将分区标记为正在分离;此时,事务将提交,并等待使用分区表的所有其他事务。一旦所有这些事务完成,第二个事务将在分区表上获取 SHARE UPDATE EXCLUSIVE 锁,并在分区上获取 ACCESS EXCLUSIVE 锁,分离过程完成。将复制分区约束的 CHECK 约束添加到分区。 CONCURRENTLY 不能在事务块中运行,如果分区表包含默认分区,则不允许使用。

如果指定 FINALIZE,则会完成先前已取消或中断的 DETACH CONCURRENTLY 调用。在一个分区表中,一次最多只能有一个分区处于待分离状态。

对单个表执行操作的所有 ALTER TABLE 形式,除了 RENAMESET SCHEMAATTACH PARTITIONDETACH PARTITION 之外,可以组合成要一起应用的多项更改列表。例如,可以在单个命令中添加多个列和/或更改多个列的类型。这对于大型表特别有用,因为只需要对表进行一次遍历即可。

您必须拥有该表才能使用 ALTER TABLE。要更改表的模式或表空间,您还必须具有对新模式或表空间的 CREATE 权限。要将表添加为父表的新子表,您还必须拥有该父表。此外,要将表作为表的新分区附加,您必须拥有要附加的表。要更改所有者,您必须能够 SET ROLE 为新的所有者角色,并且该角色必须对表的模式具有 CREATE 权限。(这些限制强制执行更改所有者不会执行任何您无法通过删除和重新创建表来执行的操作。但是,超级用户仍然可以更改任何表的所有权。)要添加列或更改列类型或使用 OF 子句,您还必须对数据类型具有 USAGE 权限。

参数

IF EXISTS #

如果表不存在,则不抛出错误。在这种情况下会发出通知。

name #

要更改的现有表(可选地带有模式限定)的名称。如果在表名称之前指定了 ONLY,则仅更改该表。如果未指定 ONLY,则会更改该表及其所有后代表(如果有)。可选地,可以在表名称后指定 * 以明确指示包含后代表。

column_name #

新列或现有列的名称。

new_column_name #

现有列的新名称。

new_name #

表的新名称。

data_type #

新列的数据类型,或现有列的新数据类型。

table_constraint #

表的新表约束。

constraint_name #

新约束或现有约束的名称。

CASCADE #

自动删除依赖于已删除列或约束的对象(例如,引用该列的视图),进而删除所有依赖于这些对象的对象(请参阅 第 5.15 节)。

RESTRICT #

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

trigger_name #

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

ALL #

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

USER #

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

index_name #

现有索引的名称。

storage_parameter #

表存储参数的名称。

value #

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

parent_table #

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

new_owner #

表的新所有者的用户名。

new_access_method #

表将转换到的访问方法的名称。

new_tablespace #

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

new_schema #

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

partition_name #

要附加为新分区或从此表中分离的表的名称。

partition_bound_spec #

新分区的分区边界规范。 有关相同语法的更多详细信息,请参阅 CREATE TABLE

注意

关键字 COLUMN 是多余的,可以省略。

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

添加具有易失性 DEFAULT 的列或更改现有列的类型将需要重写整个表及其索引。作为例外,当更改现有列的类型时,如果 USING 子句不更改列内容,并且旧类型要么可以二进制强制转换为新类型,要么是新类型上的无约束域,则不需要重写表。但是,必须始终重建索引,除非系统可以验证新索引在逻辑上等效于现有索引。例如,如果更改了列的排序规则,则始终需要重建索引,因为新的排序顺序可能不同。但是,在没有排序规则更改的情况下,可以将列从 text 更改为 varchar(或反之亦然),而无需重建索引,因为这些数据类型的排序方式相同。表和/或索引重建对于大型表可能需要大量时间;并且会暂时需要双倍的磁盘空间。

添加 CHECKNOT NULL 约束需要扫描表以验证现有行是否满足约束,但不需要重写表。

同样,当附加新分区时,可以对其进行扫描以验证现有行是否满足分区约束。

在单个 ALTER TABLE 中提供指定多个更改选项的主要原因是,这样可以将多个表扫描或重写组合到单个表遍历中。

扫描大型表以验证新的外键或检查约束可能需要很长时间,并且在提交 ALTER TABLE ADD CONSTRAINT 命令之前,对表的其他更新将被锁定。 NOT VALID 约束选项的主要目的是减少添加约束对并发更新的影响。 使用 NOT VALIDADD CONSTRAINT 命令不会扫描表,并且可以立即提交。 之后,可以发出 VALIDATE CONSTRAINT 命令以验证现有行是否满足约束。 验证步骤不需要锁定并发更新,因为它知道其他事务将对它们插入或更新的行强制执行约束;只需要检查预先存在的行。 因此,验证仅获取正在更改的表上的 SHARE UPDATE EXCLUSIVE 锁。 (如果约束是外键,则在约束引用的表上还需要 ROW SHARE 锁。)除了提高并发性之外,在已知表包含预先存在的违规的情况下,使用 NOT VALIDVALIDATE CONSTRAINT 也很有用。 一旦约束到位,就不能插入新的违规,并且可以随意纠正现有问题,直到 VALIDATE CONSTRAINT 最终成功。

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

要强制立即回收已删除列占用的空间,可以执行 ALTER TABLE 的一种形式,该形式执行整个表的重写。 这将导致使用空值替换已删除的列来重建每一行。

ALTER TABLE 的重写形式不是 MVCC 安全的。 在表重写之后,如果并发事务使用的是在重写之前拍摄的快照,则该表将对并发事务显示为空。 有关更多详细信息,请参见第 13.6 节

SET DATA TYPEUSING 选项实际上可以指定涉及行旧值的任何表达式;也就是说,它可以引用其他列以及正在转换的列。 这允许使用 SET DATA TYPE 语法进行非常通用的转换。 由于这种灵活性,USING 表达式不应用于列的默认值(如果有);结果可能不是默认值所需的常量表达式。 这意味着,当从旧类型到新类型没有隐式或赋值转换时,即使提供了 USING 子句,SET DATA TYPE 也可能无法转换默认值。 在这种情况下,请使用 DROP DEFAULT 删除默认值,执行 ALTER TYPE,然后使用 SET DEFAULT 添加合适的新默认值。 类似的考虑因素也适用于涉及列的索引和约束。

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

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

标识列的操作(ADD GENERATEDSET 等,DROP IDENTITY),以及 CLUSTEROWNERTABLESPACE 的操作永远不会递归到后代表;也就是说,它们始终表现得好像指定了 ONLY 一样。 影响触发器状态的操作会递归到分区表的分区(除非指定了 ONLY),但永远不会递归到传统的继承后代表。 添加约束仅对未标记为 NO INHERITCHECK 约束进行递归。

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

有关有效参数的更多说明,请参阅CREATE TABLE第 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';

现有行将填充 old,但随后后续命令的默认值将为 current。 效果与在单独的 ALTER TABLE 命令中发出两个子命令的效果相同。

要从表中删除列

ALTER TABLE distributors DROP COLUMN address RESTRICT;

要在一次操作中更改两个现有列的类型

ALTER TABLE distributors
    ALTER COLUMN address TYPE varchar(80),
    ALTER COLUMN name TYPE varchar(100);

通过 USING 子句将包含 Unix 时间戳的整数列更改为 timestamp with time zone

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;

兼容性

ADD(不带USING INDEX)、DROP [COLUMN]DROP IDENTITYRESTARTSET DEFAULTSET DATA TYPE(不带USING)、SET GENERATEDSET sequence_option 形式符合 SQL 标准。其他形式是 PostgreSQL 对 SQL 标准的扩展。此外,在单个 ALTER TABLE 命令中指定多个操作的能力也是一个扩展。

ALTER TABLE DROP COLUMN 可用于删除表的唯一列,留下一个零列表。 这是 SQL 的一个扩展,SQL 不允许零列表。

另请参阅

CREATE TABLE

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的体验不符或需要进一步澄清的内容,请使用 此表单报告文档问题。