Rails Migrations: попытался изменить тип столбца из строки в целое
Я создал таблицу в моем приложении rails с командой rails generate migrations. Вот файл миграции:
class CreateListings < ActiveRecord::Migration
def change
create_table :listings do |t|
t.string :name
t.string :telephone
t.string :latitude
t.string :longitude
t.timestamps
end
end
end
Затем я хотел сохранить широту и долготу как целые числа, поэтому
Я попытался запустить:
rails generate migration changeColumnType
и содержимое этого файла:
class ChangeColumnType < ActiveRecord::Migration
def up
#change latitude columntype from string to integertype
change_column :listings, :latitude, :integer
change_column :listings, :longitude, :integer
#change longitude columntype from string to integer type
end
def down
end
end
Я ожидал, что тип столбца изменится, но грабли были прерваны и появилось следующее сообщение об ошибке. Мне было интересно, почему это не прошло? Я использую postgresql в своем приложении.
rake db:migrate
== ChangeColumnType: migrating ===============================================
-- change_column(:listings, :latitude, :integer)
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::Error: ERROR: column "latitude" cannot be cast to type integer
: ALTER TABLE "listings" ALTER COLUMN "latitude" TYPE integer
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
ПРИМЕЧАНИЕ. В таблице нет DATA.
Благодаря
Ответы
Ответ 1
Я цитирую руководство about ALTER TABLE
:
Предложение USING должно быть предоставлено, если нет неявного или присвоения от старого до нового типа.
Что вам нужно:
ALTER TABLE listings ALTER longitude TYPE integer USING longitude::int;
ALTER TABLE listings ALTER latitude TYPE integer USING latitude::int;
Или короче и быстрее (для больших таблиц) в одной команде:
ALTER TABLE listings ALTER longitude TYPE integer USING longitude::int
,ALTER latitude TYPE integer USING latitude::int;
Этот работает с данными или без них, пока все записи конвертируются в integer
.
Если вы определили DEFAULT
для столбца, вам может потребоваться отбросить и воссоздать это для нового типа.
Вот статья в блоге о том, как это сделать с помощью ActiveRecord.
Или идите с комментарием @mu в комментарии. Он знает свой Рубин. Я хорошо разбираюсь в PostgreSQL здесь.
Ответ 2
Я бы включил необработанный SQL в ваш файл миграции, как показано ниже, чтобы он обновлял schema.rb.
class ChangeColumnType < ActiveRecord::Migration
def up
execute 'ALTER TABLE listings ALTER COLUMN latitude TYPE integer USING (latitude::integer)'
execute 'ALTER TABLE listings ALTER COLUMN longitude TYPE integer USING (longitude::integer)'
end
def down
execute 'ALTER TABLE listings ALTER COLUMN latitude TYPE text USING (latitude::text)'
execute 'ALTER TABLE listings ALTER COLUMN longitude TYPE text USING (longitude::text)'
end
end
Ответ 3
Я знаю это немного уродливо, но я предпочитаю просто удалить столбец и снова добавить новый тип:
def change
remove_column :mytable, :mycolumn
add_column :mytable, :mycolumn, :integer, default: 0
end
Ответ 4
Ниже приведено rails way
, чтобы подойти к проблеме. Для моего случая у меня было два столбца в моей таблице покупок, которые мне нужно было преобразовать из строки типа в float.
def change
change_column :purchases, :mc_gross, 'float USING CAST(mc_gross AS float)'
change_column :purchases, :mc_fee, 'float USING CAST(mc_fee AS float)'
end
Это помогло мне.
Ответ 5
- У вас есть существующие данные в этих столбцах?
- Вы не должны использовать int для широты и долготы. Они должны быть в плавающих точках.
Ответ 6
широта и долгота десятичная
rails g scaffold client name:string email:string 'latitude:decimal{12,3}' 'longitude:decimal{12,3}'
class CreateClients < ActiveRecord::Migration[5.0]
def change
create_table :clients do |t|
t.string :name
t.string :email
t.decimal :latitude, precision: 12, scale: 3
t.decimal :longitude, precision: 12, scale: 3
t.timestamps
end
end
end