4

我在 Postgres 中有一个大约 1M 行的表。此表中的一列存储 SMALLINT 数据。现在我需要在此列中存储比我预期的要大的数字。如何将此现有列从 SMALLINT 转换为 INTEGER?

4

2 回答 2

12

您需要将列数据类型从更改smallintinteger

alter table T alter C type integer

T 和 C 分别是表名和列名。

设置数据类型

此表单更改表格列的类型。通过重新解析最初提供的表达式,涉及该列的索引和简单表约束将自动转换为使用新的列类型。可选的 COLLATE 子句指定新列的排序规则;如果省略,则排序规则是新列类型的默认值。可选的 USING 子句指定如何从旧的列中计算新的值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。如果没有从旧类型到新类型的隐式或赋值强制转换,则必须提供 USING 子句。

请参阅ALTER TABLE文档。

于 2012-11-19T23:02:35.683 回答
5

正如 Ondrej 所说,您可以使用ALTER TABLE .. ALTER COLUMN ... TYPE INTEGER.

但是,这将触发全表重写,锁定表以防止所有并发写入或读取持续时间。这对于大型表可能很耗时。

如果您需要避免这种情况,您可以分阶段进行更改。

  • BEGIN,添加一个新的整数列和COMMIT
  • BEGIN一个事务并LOCK TABLE ... IN EXCLUSIVE MODE阻止并发插入。
  • UPDATEsmallint表,将数据复制到integer列。
  • 现在删除smallint列,将列重命名为integersmallint名称,然后COMMIT.

LOCK TABLE如果您愿意编写一个BEFORE INSERT OR UPDATE ON ... FOR EACH ROW触发器,将值从smallint列复制到integer任何INSERTor的列,您甚至可以避免并允许并发写入UPDATE。您需要在创建新整数列的同一事务中添加此触发器,以便捕获与 big UPDATE. 为了进一步减少更改对应用程序的影响,您可以在单个事务中小批量更新行,从而避免长的行级锁定。

我在之前的 dba.SE 答案中写了更多关于此的内容。

于 2012-11-20T00:20:06.077 回答