【问题标题】:Rollback migration that changes column type from string to text where db is postgresql in rails 3.2将列类型从字符串更改为文本的回滚迁移,其中 db 是 rails 3.2 中的 postgresql
【发布时间】:2014-07-24 14:38:20
【问题描述】:

我已经了解了在使用 postgresql 和 rails 3.2 提供的here 时将列类型从字符串更改为文本的解决方案。我也实现了它。但是当我回滚此迁移时,它会因“PG::StringDataRightTruncation: ERROR: value too long”错误而失败。我们应该如何解决这个问题?

【问题讨论】:

  • 嗯? PostgreSQL 中没有“字符串”类型。如果您从varchar 转换为text,那么它不会被截断。你想往另一个方向走吗?
  • @CraigRinger 我的意思是 PostgreSQL 中的 varchar,自从它用于迁移时就指定了字符串。毫无疑问,向上迁移工作正常,但向下迁移失败。需要向下迁移(即回滚)的解决方案。

标签: ruby-on-rails ruby-on-rails-3 postgresql


【解决方案1】:

您的新值对于旧类型来说太长了。如果值超过 255 个字符,PostgreSQL 将不得不丢弃数据以更改为 varchar(255)。它拒绝这样做,因为它不会在没有被明确告知这样做的情况下导致数据丢失。

如果您不介意截断这些长值,永久且不可恢复地丢弃数据,您可以使用ALTER COLUMN ... TYPEUSING 子句。这与将字符串列转换为整数时使用的方法相同。

ALTER TABLE mytable 
  ALTER COLUMN mycolumn 
  TYPE varchar(255) 
  USING (substring(mycolumn from 1 for 255));

我认为没有办法在 Rails 迁移中对称地表达这一点;向上和向下迁移需要单独的子句,向上迁移很简单:

ALTER TABLE mytable 
  ALTER COLUMN mycolumn 
  TYPE text;

但坦率地说,我认为在迁移中执行此操作是一个糟糕的主意。迁移应该失败。此操作需要管理员干预UPDATE 具有过长数据的列,然后运行迁移。

【讨论】:

  • 这正是我们所需要的。感谢您的快速帮助。
  • 将管理干预与更改表分开进行的问题是运行迁移需要时间。如果您可以冻结系统,这没有问题。但是在实时版本中,在完成管理任务和执行迁移之间的时间内,有人可以输入一个超过允许的字符串的新值,这将导致迁移失败。
  • @kikito 好点。您需要在那里将约束添加为NOT VALID,进行更改,ALTER 将约束标记为VALID 并更改类型,但不幸的是,PostgreSQL 目前仅支持NOT VALID for FOREIGN KEY 约束.您必须使用触发器来强制执行长度限制。有点乱,所以如果你能负担得起一次迁移中的停机时间是有道理的。
猜你喜欢
  • 1970-01-01
  • 2018-06-18
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
  • 2020-06-09
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多