表结构修改
当你创建一个表后,如果发现有错误,或者应用程序的需求发生变化,你可以删除这个表,然后重新创建它。但是,如果表已经包含了数据,或者表被其他数据库对象引用(比如外键约束),这就不再是一个方便的选择。因此,ProtonBase 提供了一组命令来修改已有的表。需要注意的是,这在概念上与修改表中的数据是不同的:我们关心的是修改表的定义或结构。
你可以你可以进行以下操作:
所有这些操作都使用ALTER TABLE
命令来执行,更详细的信息使用方法请参考Modifying Tables
,这里提供的是基本信息。
添加列
假设原始表是通过以下命令创建的:
CREATE TABLE products (
product_no integer,
name text,
price numeric
);
要添加一列,可以使用如下命令:
ALTER TABLE products ADD COLUMN description text;
新的列最初会被填充为给定的默认值(如果没有指定 DEFAULT 子句,则为 NULL)。
注意: 如果添加的列具备一个确定性的默认值,ProtonBase 会避免在执行 ALTER TABLE 语句时就将更新表的每一行。相反,这个列会在下次访问时返回默认值。这样即使在一张很大的表上,ALTER TABLE 也会非常快速。
然而,如果默认值是不稳定的(例如,clock_timestamp()),则 ALTER TABLE 执行时则需要更新表的每一行。ProtonBase 会尝试使用 Online Schema Change 的技术来避免该表被长时间的锁住而导致不可读写。
你还可以同时在列上定义约束,使用通常的语法:
ALTER TABLE products ADD COLUMN description text CHECK (description <> '');
实际上,在 CREATE TABLE 中可以应用到该列的所有选项都可以在这里使用。然而请注意,默认值必须满足给定的约束,否则添加操作将失败。或者,你可以稍后添加约束(见下文),在你正确填充了新列之后。
删除列
要删除一列,可以使用如下命令:
ALTER TABLE products DROP COLUMN description;
该列中的所有数据都会被删除。涉及该列的表约束也会被删除。然而,如果该列被另一个表的外键约束引用,ProtonBase 不会自动删除该约束。你可以通过添加 CASCADE 授权删除依赖于该列的所有内容:
ALTER TABLE products DROP COLUMN description CASCADE;
添加约束
要添加约束,使用表约束的语法。例如:
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;
这实际上与将默认值设置为 NULL 是一样的。因此,如果没有定义默认值,删除一个默认值并不会报错,因为默认值隐式地是 NULL 值。
修改列的数据类型
要将列转换为不同的数据类型,可以使用以下命令:
ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);
只有当该列中的每个现有条目都可以通过隐式转换转换为新类型时,此操作才会成功。如果需要更复杂的转换,你可以添加 USING 子句,该子句指定如何从旧值计算新值。
ProtonBase 将尝试将该列的默认值(如果有)转换为新类型,以及任何涉及该列的约束。但是,这些转换可能失败,或者可能产生意想不到的结果。通常最好在修改列的类型之前删除该列上的任何约束,然后在之后添加适当修改后的约束。
重命名列
要重命名列:
ALTER TABLE products RENAME COLUMN product_no TO product_number;
重命名表
要重命名一个表:
ALTER TABLE products RENAME TO items;