Postgresql 中文操作指南
5.6. Modifying Tables #
当您创建一个表并且意识到自己犯了一个错误,或者应用程序的要求发生了更改时,您可以删除表并再次创建它。但如果表中已填充了数据,或者表被其他数据库对象引用(例如外键约束),则这不是一个方便的选项。因此,PostgreSQL 提供了一系列命令来修改现有表。请注意,这在概念上不同于更改表中包含的数据:在这里我们有兴趣更改表的定义或结构。
您可以执行以下操作:
所有这些操作使用 ALTER TABLE 命令执行,其参考页面包含此处所给详细信息以外的详细信息。
5.6.1. Adding a Column #
要添加一列,请使用如下命令:
ALTER TABLE products ADD COLUMN description text;
最初,新列会使用提供的任何默认值进行填充(如果您没有指定 DEFAULT 子句,则为 null)。
Tip
从 PostgreSQL 11 开始,添加具有常量默认值的一列不再意味着需要在执行 ALTER TABLE 语句时更新表的每一行。相反,将在下次访问行时返回默认值,并在重写表时应用,从而使 ALTER TABLE 即使在大型表上也能非常快。
但是,如果默认值不稳定(例如,clock_timestamp()),则需要使用在执行 ALTER TABLE 时计算的值更新每一行。为了避免潜在的冗长更新操作(尤其是如果您打算主要用非默认值填充列时),最好不添加默认值来添加列、使用 UPDATE 插入正确的值,然后按以下说明添加任何所需的默认值。
您还可以使用常规语法同时定义列上的约束:
ALTER TABLE products ADD COLUMN description text CHECK (description <> '');
事实上,可以应用于 CREATE TABLE 中列描述的所有选项都可以用在这里。然而,请记住,默认值必须满足给定的约束,否则 ADD 将失败。或者,您也可以在正确填充新列后稍后添加约束(见下文)。
5.6.2. Removing a Column #
要移除列,请使用如下命令:
ALTER TABLE products DROP COLUMN description;
列中的任何数据都会消失。涉及该列的表约束也会被删除。但是,如果该列由其他表的外部键约束引用,PostgreSQL 不会静默地删除该约束。您可以通过添加 CASCADE 授权删除依赖于该列的所有内容:
ALTER TABLE products DROP COLUMN description CASCADE;
有关此机制背后的常规描述,请参见 Section 5.14。
5.6.3. Adding a Constraint #
要添加约束,请使用表约束语法。例如:
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;
将立即检查约束,因此表数据必须满足约束才能将其添加进去。
5.6.4. Removing a Constraint #
要消除约束,您需要知道其名称。如果您给了它一个名称,那么就很容易。否则,系统会分配一个生成的名称,您需要了解它。psql 命令 \d _tablename_ 在此处可给予帮助;其他接口也可能提供一种检查表详细信息的方法。然后,命令为:
ALTER TABLE products DROP CONSTRAINT some_name;
(如果您处理的是像 $2 这样的生成约束名称,请不要忘记您需要用双引号引起来使其成为有效的标识符。)
与删除列一样,如果您要删除别的什么东西所依赖的约束,则需要添加 CASCADE。一个例子是外部键约束依赖于引用列上的唯一或主键约束。
这适用于除非空约束之外的所有约束类型。要删除非空约束,请使用:
ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;
(回想一下,非空约束没有名称。)
5.6.5. Changing a Column’s Default Value #
要为列设置新的默认值,请使用如下命令:
ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;
请注意,这不会影响表中的任何现有行,它只会更改未来 INSERT 命令的默认值。
要移除任何默认值,请使用:
ALTER TABLE products ALTER COLUMN price DROP DEFAULT;
这实际上与将默认值设置为 null 相同。因此,删除尚未定义默认值不是错误,因为默认值隐式为 null 值。
5.6.6. Changing a Column’s Data Type #
要将列转换为不同的数据类型,请使用诸如以下的命令:
ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);
只有在列中的现有条目可以通过隐式转换转换为新类型时,此命令才会成功。如果需要更复杂的转换,您可以添加 USING 子句,该子句指定如何从旧值计算新值。
PostgreSQL 将尝试将列的默认值(如果有)转换为新类型,以及涉及该列的所有约束。但这些转换可能会失败,或可能产生意外的结果。在更改列的类型之前,通常最好先删除列上的所有约束,然后在之后添加适当修改的约束。