ruby-on-rails Rails迁移更改列以使用Postgres阵列

mwngjboj  于 2023-02-17  发布在  Ruby
关注(0)|答案(6)|浏览(186)

我正在尝试更改数据库中的列,以便它可以使用Postgres数组数据类型。当前表列的类型为string。
我正在使用以下迁移来转换它:

def change
  change_column :table, :dummy_column, :text, array: true, default: []
end

但我得到了以下错误:

bundle exec rake db:migrate
rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  column "dummy_column" cannot be cast automatically to type     character varying[]
HINT:  Specify a USING expression to perform the conversion.
: ALTER TABLE "table" ALTER COLUMN "dummy_column" TYPE character varying(255) 
Tasks: TOP => db:migrate
yks3o0rb

yks3o0rb1#

PostgreSQL不知道如何自动将varchar列转换为varchar数组,也不知道你想要什么,因为它无法知道你认为当前值是什么格式。
所以你要告诉它;这就是USING子句的作用。
ActiveRecord似乎不显式支持USING子句(这并不奇怪,因为它几乎不支持最基本的数据库特性),不过您可以为迁移指定自己的SQL文本。
假设您的字符串以逗号分隔,并且本身可能不包含逗号,例如:

def change
  change_column :table, :dummy_column, "varchar[] USING (string_to_array(dummy_column, ','))"
end

(我自己不使用Rails,也没有测试过,但它与其他地方的示例中使用的语法是一致的)。

qlzsbp2j

qlzsbp2j2#

在postgresql9.4上使用Rails4.2时,我希望这样做,并将预先存在的字符串数据保留为单元素数组中的第一个元素。
事实证明,如果没有USING表达式告诉postgresql如何将字符串强制转换为文本数组,postgresql就无法将字符串强制转换为文本数组。
在对postgres语法进行了大量的修改之后,我找到了一个使用active record的中间方法:

def change
  change_column :users, :event_location, :text, array: true, default: [], using: "(string_to_array(event_location, ','))"
end

唯一直接的postgresql是(string_to_array() )函数调用。Here are the docs on that--注意,必须提供一个分隔符。

kokeuurv

kokeuurv3#

在postgresql 9.4上使用Rails 4.2,带有down和up,基于lrthomas响应。起始列的缺省值应为nil

class ChangeEmailAndNumberColumnForContact < ActiveRecord::Migration
  def up
    change_column :contacts, :mobile_number, :text, array: true, default: [], using: "(string_to_array(mobile_number, ','))"
    change_column :contacts, :email, :text, array: true, default: [], using: "(string_to_array(email, ','))"
  end

  def down
    change_column :contacts, :mobile_number, :text, array: false, default: nil, using: "(array_to_string(mobile_number, ','))"
    change_column :contacts, :email, :text, array: false, default: nil, using: "(array_to_string(email, ','))"
  end
end
ru9i0ody

ru9i0ody4#

def change

    change_column :table, :dummy_column, :string, array: true, default: '{}'

end

注意事项:
它被指定为数据类型:字符串和数组:true将列默认为空数组([]),则使用default:'{}'

xfyts7mz

xfyts7mz5#

可以按如下方式完成:

change_column :table, :column, :string, array: true, default: {}, using: "(string_to_array(column, ','))"
olmpazwi

olmpazwi6#

add_column :table, :dummy_column, :string, array: true
change_column_default :table, :dummy_column, []

这个帮我修好了。

相关问题