Rails迁移:将列类型从text更改为json(Postgresql)

11

我一直在尝试将Postgres数据库中的一列类型从文本更改为json,但未成功。以下是我尝试过的方法...

class ChangeNotesTypeInPlaces < ActiveRecord::Migration[5.0]
  def up
    execute 'ALTER TABLE places ALTER COLUMN notes TYPE json USING (notes::json)'
  end

  def down
    execute 'ALTER TABLE places ALTER COLUMN notes TYPE text USING (notes::text)'
  end
end

另外...

class ChangeNotesTypeInPlaces < ActiveRecord::Migration[5.0]
  def up
    change_column :places, :notes, 'json USING CAST(notes AS json)'
  end

  def down
    change_column :places, :notes, 'text USING CAST(notes AS text)'
  end
end

这两种都会返回相同的错误...

PG::InvalidTextRepresentation: ERROR:  invalid input syntax for type json

notes列已经有一个不是有效JSON的值了吗? - jamesjaya
这是个好问题。我之前从未在这个列中存储过数据(在开发环境中,不幸的是在生产环境中情况并非如此),但该列也没有非空约束。可能是它将一个空字符串保存到该列中导致了这个问题?如果是这样的话,你知道我怎么可以解决这个问题吗? - soultrust
1
如果您没有非空约束,那么空值将是可以的,或者您可以保存空的JSON {}。它不接受空字符串。 - jamesjaya
3个回答

13

使用Rails 5.1.x和PostgreSQL 9.4,在将包含有效JSON的文本列转换为JSONB列时,以下方法适用于我:

class ChangeTextColumnsToJson < ActiveRecord::Migration[5.1]
  def change
    change_column :table_name, :column_name, :jsonb, using: 'column_name::text::jsonb'
  end
end

1
这在postgres 9.6 rails 5.1中有效,我不得不添加反向操作:def down change_column :table_name, :column_name, :text end - ipopa
1
这个相同的解决方案适用于 AR::Migration[6.1],一如既往,请确保数据有效,否则建议添加列、复制数据并重命名列。 - Carlos J García

2
我可以使用以下方法来实现它:
def change
  change_column :places, :notes, :json, using: 'notes::JSON'
end

不过这是不可逆的;我想你可以将其分成单独的向上和向下定义,但我觉得没有必要。


1
应该将 updown 分开。 - rj487

0

我刚刚解决了一个类似的问题。为了适应你的问题,它看起来(大部分)像这样。

class ChangeNotesTypeInPlaces < ActiveRecord::Migration[5.0]
  def up
    change_column :places, :notes, :jsonb, using: 'CAST(value AS JSON)'
  end

  def down
    change_column :places, :notes, :text
  end
end

1
如果在 CAST 中将单词“value”替换为“notes”,那么对我来说是有效的。 - Eli R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接