创建表之后,如果你意识到自己犯了错误,或者应用需求发生了变化,可以删掉表再重新创建。但如果表中已经有数据,或者该表已被其他数据库对象引用(例如被外键约束引用),这样做就不方便了。因此,PostgreSQL提供了一组命令来修改现有表。注意,这在概念上不同于修改表中保存的数据:这里关注的是修改表的定义,也就是表的结构。
利用这些命令,我们可以:
增加列
移除列
增加约束
移除约束
修改默认值
修改列数据类型
重命名列
重命名表
所有这些动作都由ALTER TABLE命令执行,其参考页面中包含更详细的信息。
要添加一列,可以使用这样的命令:
ALTER TABLE products ADD COLUMN description text;
新列最初会填入给定的默认值(如果没有指定DEFAULT子句,则为填入空值)。
从PostgreSQL 11 开始,添加带有常量默认值的列时,在执行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.13。
添加约束时使用表约束语法。例如:
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;
(如果处理的是自动生成的约束名,例如$2,别忘了加上双引号,使其成为有效标识符。)
和删除列一样,如果要删除某些其他对象所依赖的约束,也需要加上CASCADE。例如,外键约束就依赖于被引用列上的唯一约束或主键约束。
除非空约束之外,所有类型的约束都可以用相同方式删除。要删除非空约束,使用:
ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;
(请记住,非空约束没有名称。)
要为一个列设置一个新默认值,使用命令:
ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;
注意这不会影响任何表中已经存在的行,它只是为未来的INSERT命令改变了默认值。
要移除任何默认值,使用:
ALTER TABLE products ALTER COLUMN price DROP DEFAULT;
这等同于将默认值设置为空值。相应的,试图删除一个未被定义的默认值并不会引发错误,因为默认值已经被隐式地设置为空值。