Rails Migration change column используется для использования массивов Postgres

Я пытаюсь изменить столбец в моей базе данных, чтобы он мог использовать тип данных массива Postgres. В настоящее время столбец таблицы имеет строку типа.

Я использую следующую миграцию для ее преобразования:

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

Ответ 1

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

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

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

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

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

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

Ответ 2

Использование 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() ). Вот документы на этом - отметьте, что вам нужно предоставить разделитель.

Ответ 3

def change

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

end

Примечание:

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

Ответ 4

Использование Rails 4.2 в postgresql 9.4 с уменьшением и увеличением, основанием для ответа lrrthomas. Примечание: стартовая колонка должна иметь значение по умолчанию 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