Столбец изменения миграции Rails для использования массивов Postgres

Я пытаюсь изменить столбец в моей базе данных, чтобы он мог использовать тип данных массива 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

4 ответов


PostgreSQL не знает, как автоматически преобразовать столбец varchar в массиве varchar. Он не знает, что вы можете намереваться, потому что он не может знать, в каком формате вы думаете текущие значения.

так что вам нужно сказать это; вот что USING предложение для.

ActiveRecord, похоже, явно не поддерживает USING предложение (не удивительно, так как оно едва поддерживает даже самые основные функции базы данных). Вы можете указать свой собственный Однако текст SQL для миграции.

предполагая, что ваши строки разделены запятыми и не могут сами содержать запятые, например:

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

(Я сам не использую Rails и не тестировал это, но это согласуется с синтаксисом, используемым в примерах в другом месте).


используя Rails 4.2 на postgresql 9.4 я хотел сделать это и сохранить мои ранее существующие строковые данные в качестве первого элемента в массивах одного элемента.

оказывается, postgresql не может принудительно ввести строку в текстовый массив без выражения USING, чтобы сказать, как это сделать.

после долгой возни с тонким синтаксисом postgres я нашел хороший средний путь с активной записью:

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

единственным прямым postgresql является (string_to_array() ) вызов функции. вот документы об этом--обратите внимание, что вы должны поставить разделитель.


использование Rails 4.2 на postgresql 9.4 с down и up, на основе ответа lrrthomas. Примечание: ваш начальный столбец должен иметь значение по умолчанию шь

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

def change

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

end

обратите внимание:

он указан как тип данных: строка с массивом: true по умолчанию столбец пустого массива ([]), вы используете по умолчанию: '{}'