我在我的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)
注意:该表没有数据。谢谢
我引用了关于ALTER TABLE
的手册:
如果没有隐式或转让,则必须提供
USING
条款从旧类型到新类型。
您需要的是:
更改表列表 使用 longitude::int 更改经度类型整数;更改表列表 使用 LATITUDE::INT 更改纬度类型整数;
或者在一个命令中更短更快(对于大表):
ALTER TABLE listings
ALTER longitude TYPE integer USING longitude::int
, ALTER latitude TYPE integer USING latitude::int;
只要所有条目都integer
有效,只要所有条目都有效,只要 .
如果列有DEFAULT
,则可能必须删除该列(在上述之前)并为新类型重新创建(在上述之后)。
这是一篇关于如何使用 ActiveRecord.
执行此操作的博客文章或者在评论中遵循@mu的建议。他知道他的红宝石。我只对PostgreSQL部分很了解。
我会像下面这样将原始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
这有点丑,但我更喜欢删除该列并使用新类型再次添加:
def change
remove_column :mytable, :mycolumn
add_column :mytable, :mycolumn, :integer, default: 0
end
以下是解决此问题的更rails way
。就我而言,我的购买表中有两列,我需要从字符串类型转换为浮点数。
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
这对我来说起到了作用。
- 这些列中是否有现有数据?
- 不应将 int 用于纬度和经度。它们应该位于浮点中。
纬度和经度是十进制
的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