我在 Postgres 中有一个大约 1M 行的表。此表中的一列存储 SMALLINT 数据。现在我需要在此列中存储比我预期的要大的数字。如何将此现有列从 SMALLINT 转换为 INTEGER?
2 回答
您需要将列数据类型从更改smallint
为integer
:
alter table T alter C type integer
T 和 C 分别是表名和列名。
设置数据类型
此表单更改表格列的类型。通过重新解析最初提供的表达式,涉及该列的索引和简单表约束将自动转换为使用新的列类型。可选的 COLLATE 子句指定新列的排序规则;如果省略,则排序规则是新列类型的默认值。可选的 USING 子句指定如何从旧的列中计算新的值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。如果没有从旧类型到新类型的隐式或赋值强制转换,则必须提供 USING 子句。
请参阅ALTER TABLE文档。
正如 Ondrej 所说,您可以使用ALTER TABLE .. ALTER COLUMN ... TYPE INTEGER
.
但是,这将触发全表重写,锁定表以防止所有并发写入或读取持续时间。这对于大型表可能很耗时。
如果您需要避免这种情况,您可以分阶段进行更改。
BEGIN
,添加一个新的整数列和COMMIT
。BEGIN
一个事务并LOCK TABLE ... IN EXCLUSIVE MODE
阻止并发插入。UPDATE
smallint
表,将数据复制到integer
列。- 现在删除
smallint
列,将列重命名为integer
的smallint
名称,然后COMMIT
.
LOCK TABLE
如果您愿意编写一个BEFORE INSERT OR UPDATE ON ... FOR EACH ROW
触发器,将值从smallint
列复制到integer
任何INSERT
or的列,您甚至可以避免并允许并发写入UPDATE
。您需要在创建新整数列的同一事务中添加此触发器,以便捕获与 big UPDATE
. 为了进一步减少更改对应用程序的影响,您可以在单个事务中小批量更新行,从而避免长的行级锁定。
我在之前的 dba.SE 答案中写了更多关于此的内容。