选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.0 已于 2015 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

ALTER TABLE

ALTER TABLE — 更改一个表的定义

大纲

ALTER TABLE [ ONLY ] name [ * ]
    action [, ... ]
ALTER TABLE [ ONLY ] name [ * ]
    RENAME [ COLUMN ] column TO new_column
ALTER TABLE name
    RENAME TO new_name
ALTER TABLE name
    SET SCHEMA new_schema

where action is one of:

    ADD [ COLUMN ] column type [ column_constraint [ ... ] ]
    DROP [ COLUMN ] [ IF EXISTS ] column [ RESTRICT | CASCADE ]
    ALTER [ COLUMN ] column [ SET DATA ] TYPE type [ USING expression ]
    ALTER [ COLUMN ] column SET DEFAULT expression
    ALTER [ COLUMN ] column DROP DEFAULT
    ALTER [ COLUMN ] column { SET | DROP } NOT NULL
    ALTER [ COLUMN ] column SET STATISTICS integer
    ALTER [ COLUMN ] column SET ( attribute_option = value [, ... ] )
    ALTER [ COLUMN ] column RESET ( attribute_option [, ... ] )
    ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
    ADD table_constraint
    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
    CLUSTER ON index_name
    SET WITHOUT CLUSTER
    SET WITH OIDS
    SET WITHOUT OIDS
    SET ( storage_parameter = value [, ... ] )
    RESET ( storage_parameter [, ... ] )
    INHERIT parent_table
    NO INHERIT parent_table
    OWNER TO new_owner
    SET TABLESPACE new_tablespace

描述

ALTER TABLE更改一个现有表的定义。它有若干种子形式:

ADD COLUMN

这种形式使用与 CREATE TABLE 相同的语法向表添加一个新列。

DROP COLUMN [ IF EXISTS ]

这种形式从表中删除一个列。涉及该列的索引和表约束也将被自动删除。如果表外的任何对象依赖于该列(例如外键引用或视图),则需要指定 CASCADE。如果指定了 IF EXISTS 而该列不存在,则不会抛出错误,而是发出一个提示。

SET DATA TYPE

这种形式更改表中某一列的类型。涉及该列的索引和简单表约束会通过重新解析最初提供的表达式,自动转换为使用新的列类型。可选的USING子句指定如何根据旧值计算新列值;如果省略,默认转换与从旧数据类型到新数据类型的赋值转换相同。如果旧类型到新类型之间不存在隐式转换或赋值转换,则必须提供USING子句。

SET/DROP DEFAULT

这些形式为列设置或移除默认值。默认值只会应用于后续的 INSERT 命令;它们不会导致表中已有的行发生变化。也可以为视图创建默认值,这种情况下,在应用视图的 ON INSERT 规则之前,默认值会被插入到视图上的 INSERT 语句中。

SET/DROP NOT NULL

这些形式更改列是否被标记为允许空值,或拒绝空值。只有当列不包含空值时,才能使用SET NOT NULL

SET STATISTICS

该形式为后续ANALYZE操作设置每列的统计信息收集目标。目标可以设置在 0 到 10000 范围内;也可以将其设置为 -1,以恢复使用系统默认的统计目标(default_statistics_target)。有关PostgreSQL查询规划器使用统计信息的更多信息,请参见第 14.2 节

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 节

SET STORAGE

该形式为列设置存储模式。这控制该列是内联保存还是保存在辅助TOAST表中,以及是否压缩数据。对于integer等定长值,必须使用PLAIN,数据以内联且未压缩的形式保存。MAIN用于内联的可压缩数据。EXTERNAL用于外部保存的未压缩数据,EXTENDED用于外部保存的压缩数据。对于支持非PLAIN存储的大多数数据类型,EXTENDED是默认值。使用EXTERNAL会使非常大的textbytea值上的子字符串操作运行得更快,但会增加存储空间。请注意,SET STORAGE本身不会更改表中的任何内容,它只会设置今后更新表时采用的策略。更多信息请参见第 54.2 节

ADD table_constraint

这种形式使用与CREATE TABLE相同的语法向一个表增加一个新约束。

DROP CONSTRAINT [ IF EXISTS ]

该形式从表中删除指定的约束。如果指定IF EXISTS且约束不存在,则不会抛出错误;在这种情况下会发出通知。

DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER

这些形式配置属于表的触发器的触发。已禁用的触发器仍为系统所知,但在触发事件发生时不会执行。对于延迟触发器,会在事件发生时检查启用状态,而不是在实际执行触发器函数时检查。可以按名称指定单个触发器,或指定表上的所有触发器,或仅指定用户触发器,从而禁用或启用触发器(最后一种选项不包括内部生成的约束触发器,例如用于实现外键约束或可延迟唯一性约束和排他约束的触发器)。禁用或启用内部生成的约束触发器需要超级用户权限;应谨慎操作,因为如果不执行触发器,当然无法保证约束的完整性。触发器触发机制还会受到配置变量session_replication_role的影响。简单启用的触发器会在复制角色为origin(默认值)或local时触发。配置为ENABLE REPLICA的触发器只会在会话处于replica模式时触发,配置为ENABLE ALWAYS的触发器则无论当前复制模式为何都会触发。

DISABLE/ENABLE [ REPLICA | ALWAYS ] RULE

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

CLUSTER

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

SET WITHOUT CLUSTER

该形式从表中移除最近使用的CLUSTER索引规范。这会影响将来的聚簇操作(这些操作未指定索引)。

SET WITH OIDS

该形式向表添加一个oid系统列(参见第 5.4 节)。如果表已有 OID,则不执行任何操作。

请注意,这并不等同于ADD COLUMN oid oid;后者会添加一个碰巧命名为oid的普通列,而不是系统列。

SET WITHOUT OIDS

该形式从表中移除oid系统列。这完全等同于DROP COLUMN oid RESTRICT,但如果表中已经没有oid列,则不会报错。

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

这种形式更改表的一个或多个存储参数。可用参数的细节见存储参数。注意,该命令不会立即修改表内容;根据参数的不同,你可能需要重写表才能获得想要的效果。这可以通过CLUSTERALTER TABLE中会强制重写表的某种形式来完成。

注意

虽然CREATE TABLE允许在WITH (storage_parameter)语法中指定OIDS,但ALTER TABLE不会将OIDS视为存储参数。应改用SET WITH OIDSSET WITHOUT OIDS形式来更改 OID 状态。

RESET ( storage_parameter [, ... ] )

该形式把一个或多个存储参数重置为默认值。与SET一样,可能仍需要进行表重写才能让整张表完全更新。

INHERIT parent_table

该形式将目标表添加为指定父表的新子表。之后,对父表执行的查询将包含目标表的记录。要作为子表添加,目标表必须已经包含与父表相同的所有列(也可以有额外的列)。列必须具有匹配的数据类型;如果父表中的列具有NOT NULL约束,则子表中的相应列也必须具有NOT NULL约束。

父表的所有 CHECK 约束还必须在子表中有匹配的约束。目前不考虑 UNIQUEPRIMARY KEYFOREIGN KEY 约束,但将来可能会改变。

NO INHERIT parent_table

该形式把目标表从指定父表的子表列表中移除。对父表的查询将不再包含来自目标表的记录。

OWNER

该形式把表、序列或视图的所有者更改为指定用户。

SET TABLESPACE

这种形式把表的表空间更改为指定的表空间,并把与该表关联的数据文件移动到新表空间。表上的索引(如果有)不会被移动;但可以用额外的 SET TABLESPACE 命令单独移动。另见 CREATE TABLESPACE

RENAME

RENAME 形式更改表(或索引、序列或视图)的名称,或者更改表中某一列的名称。存储的数据不受影响。

SET SCHEMA

该形式把表移动到另一个模式。相关索引、约束以及由表列拥有的序列也会一并移动。

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

要使用 ALTER TABLE,必须拥有该表。要更改表的模式,还必须在新模式上拥有 CREATE 权限。要将表作为父表的新子表添加,还必须拥有父表。要更改所有者,还必须是新所有者角色的直接或间接成员,并且该角色必须在表所在模式上拥有 CREATE 权限。(这些限制确保更改所有者不会执行任何无法通过删除并重新创建该表完成的操作。不过,超级用户无论如何都可以更改任何表的所有权。)

参数

name

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

column

新列或现有列的名称。

new_column

现有列的新名称。

new_name

表的新名称。

type

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

table_constraint

表的新约束。

constraint_name

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

CASCADE

自动删除依赖于被删除列或约束的对象(例如引用该列的视图)。

RESTRICT

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

trigger_name

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

ALL

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

USER

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

index_name

现有索引的名称。

storage_parameter

表存储参数的名称。

value

表存储参数的新值。根据参数的不同,这可以是数字或单词。

parent_table

要与该表关联或解除关联的父表。

new_owner

表的新所有者的用户名。

new_tablespace

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

new_schema

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

Notes

关键字COLUMN只是噪声,可以省略。

使用ADD COLUMN添加列时,表中的所有现有行都会使用该列的默认值初始化(如果未指定DEFAULT子句,则使用 NULL)。如果没有 DEFAULT 子句,这只是一次元数据更改,不需要立即更新表数据;添加的 NULL 值会在读取时提供。

增加一个带非空默认值的列或更改一个现有列的类型将要求重写整个表及其索引。这对于大型表可能需要相当长的时间,并且会暂时需要两倍的磁盘空间。增加或删除系统oid列同样要求重写整个表。

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

允许在单条ALTER TABLE命令中指定多项更改,主要是因为这样可以将多次表扫描或重写合并为一次遍历。

DROP COLUMN形式不会从物理上删除列,而只是使其对 SQL 操作不可见。表后续的插入和更新操作会为该列存储空值。因此,删除列的速度很快,但不会立即减少表在磁盘上的大小,因为被删除列占用的空间不会被回收。随着现有行被更新,空间会逐渐回收。(删除系统oid列时不适用这些说明;删除该列会立即重写表。)

SET DATA TYPE要求重写整个表这一事实有时反而是一个优点,因为重写过程会清除表中的任何死空间。例如,要立即回收一个被删除列占用的空间,最快的方式是:

ALTER TABLE table ALTER COLUMN anycol TYPE anytype;

其中anycol是表中任意一个剩余的列,而anytype是该列已有的类型。这不会对表产生任何语义上可见的改变,但该命令会强制重写,从而清除不再有用的数据。

会重写表的ALTER TABLE形式对于 MVCC 来说并不安全。表重写完成后,如果并发事务使用的是在重写发生之前取得的快照,那么该表在这些并发事务看来会像一张空表。详见第 13.5 节

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

如果表有任何后代表,则不允许只在父表中添加、重命名或更改列的类型,或重命名继承的约束,而不对后代表执行相同操作。也就是说,ALTER TABLE ONLY会被拒绝。这确保后代表始终拥有与父表匹配的列。

只有当某个后代表中的列既不是从其他父表继承而来,也从未有过该列的独立定义时,递归的DROP COLUMN操作才会移除该后代表中的此列。非递归的DROP COLUMN(即ALTER TABLE ONLY ... DROP COLUMN)永远不会移除任何后代列,而只会把它们标记为独立定义,而非继承得到。

TRIGGERCLUSTEROWNERTABLESPACE 操作永远不会递归到后代表;也就是说,它们的行为始终如同指定了 ONLY。添加约束时,只有 CHECK 约束可以递归,而且对这类约束必须递归。

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

有关有效参数的进一步说明,请参见CREATE TABLE第 5 章中还有关于继承的更多信息。

示例

要添加类型为varchar的列到表中:

ALTER TABLE distributors ADD COLUMN address varchar(30);

要从表中删除一列:

ALTER TABLE distributors DROP COLUMN address RESTRICT;

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

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

要把一个包含 Unix 时间戳的整数列改为 timestamp with time zone,并通过USING子句完成转换:

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 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 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 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;

兼容性

The forms ADD, DROP, SET DEFAULT, and SET DATA TYPE (without USING) conform with the SQL standard. The other forms are PostgreSQL extensions of the SQL standard. 此外,在单条ALTER TABLE命令中指定多个操作的能力也是一种扩展。

ALTER TABLE DROP COLUMN可以被用来删除一个表的唯一的 列,从而留下一个零列的表。这是一种 SQL 的扩展,SQL 中不允许零列的表。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。