创建表之后,如果你意识到自己犯了错误,或者应用需求发生了变化,可以删掉表再重新创建。但如果表中已经有数据,或者该表已被其他数据库对象引用(例如被外键约束引用),这样做就不方便了。因此,PostgreSQL提供了一组命令来修改现有表。注意,这在概念上不同于修改表中保存的数据:这里关注的是修改表的定义,也就是表的结构。
利用这些命令,我们可以:
增加列
移除列
增加约束
移除约束
修改默认值
修改列数据类型
重命名列
重命名表
所有这些动作都由ALTER TABLE命令执行,其参考页面中包含更详细的信息。
要添加一列,可以使用这样的命令:
ALTER TABLE products ADD COLUMN description text;
新列最初会填入给定的默认值(如果没有指定DEFAULT子句,则为填入空值)。
添加带有常量默认值的列时,在执行ALTER TABLE语句时并不需要更新表中的每一行。相反,该默认值会在下一次访问该行时返回,并在表被重写时应用,因此即使面对大表,ALTER TABLE也会非常快。
如果默认值是易变的(例如clock_timestamp()),则每一行都需要更新为执行ALTER TABLE时计算出的值。为避免潜在的长时间更新操作,特别是在你本来就打算用大多数非默认值填充该列时,更好的做法可能是先添加一个没有默认值的列,用UPDATE填入正确的值,然后再按下文所述添加所需的默认值。
也可以同时为该列定义约束,使用常规语法:
ALTER TABLE products ADD COLUMN description text CHECK (description <> '');
实际上,凡是在CREATE TABLE中可用于列描述的选项,在这里都可以使用。不过要记住,默认值必须满足给定约束,否则ADD就会失败。另一种做法是先把新列正确填好,再在之后添加约束(见下文)。
要删除一列,使用如下命令:
ALTER TABLE products DROP COLUMN description;
该列中的数据会消失,涉及该列的表约束也会被删除。不过,如果该列被其他表的外键约束引用,PostgreSQL不会静默删除该约束。你可以通过添加CASCADE来授权删除所有依赖该列的对象:
ALTER TABLE products DROP COLUMN description CASCADE;
关于这个操作背后的一般性机制请见Section 5.15。
要添加约束,可以使用表约束语法,例如:
ALTER TABLE products ADD CHECK (name <> ''); ALTER TABLE products ADD CONSTRAINT some_name UNIQUE (product_no); ALTER TABLE products ADD FOREIGN KEY (product_group_id) REFERENCES product_groups;
要添加一个通常不会写成表约束形式的非空约束,可以使用这个特殊语法:
ALTER TABLE products ALTER COLUMN product_no SET NOT NULL;
该命令在列已经具有非空约束时会静默地不做任何事。
约束会立即被检查,因此必须先保证表中的数据满足约束,然后才能添加该约束。
要删除约束,首先需要知道它的名称。如果你在创建时给它指定了名称,这很容易;否则就需要先查出系统生成的名称。psql命令\d 在这里会很有帮助,其他接口也可能提供查看表详细信息的方法。然后命令是:tablename
ALTER TABLE products DROP CONSTRAINT some_name;
和删除列一样,如果要删除某些其他对象所依赖的约束,也需要加上CASCADE。例如,外键约束就依赖于被引用列上的唯一约束或主键约束。
对于删除非空约束,则有简化语法可用:
ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;
这与添加非空约束时的SET NOT NULL语法相对应。如果该列没有非空约束,这条命令会静默地不做任何事。(记住,一列最多只能有一个非空约束,因此这条命令作用于哪个约束并不存在歧义。)
要为一个列设置一个新默认值,使用命令:
ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;
注意这不会影响任何表中已经存在的行,它只是为未来的INSERT命令改变了默认值。
要移除任何默认值,使用:
ALTER TABLE products ALTER COLUMN price DROP DEFAULT;
这等同于将默认值设置为空值。相应的,试图删除一个未被定义的默认值并不会引发错误,因为默认值已经被隐式地设置为空值。
为了将一个列转换为一种不同的数据类型,使用如下命令:
ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);
只有当列中的每一个项都能通过一个隐式类型转换为新的类型时该操作才能成功。如果需要一种更复杂的转换,应该加上一个USING子句来指定应该如何把旧值转换为新值。
PostgreSQL将尝试把列的默认值转换为新类型,其他涉及到该列的任何约束也是一样。但是这些转换可能失败或者产生奇特的结果。因此最好在修改类型之前先删除该列上所有的约束,然后在修改完类型后重新加上相应修改过的约束。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。