Rails移植:试图从字符串改变列的类型整数(Rails Migrations: tried to

2019-06-24 00:02发布

我创建了一个表,我的Rails应用程序使用Rails生成迁移命令。 下面是迁移文件:

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)

注:表中没有任何数据。 谢谢

Answer 1:

我引用手动约ALTER TABLE

如果从旧到新类型没有隐含或者赋值转换必须提供使用条款。

你需要的是:

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做这个博客文章 。
或在评论@亩的意见走。 他知道自己的红宝石。 我只在这里PostgreSQL的好。



Answer 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


Answer 3:

我知道这有点难看,但我更愿意只删除列,并与新型再次添加:

 def change
     remove_column :mytable, :mycolumn
     add_column :mytable, :mycolumn, :integer, default: 0
 end


Answer 4:

下面是一个更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

这奏效了我。



Answer 5:

  1. 你是否已经存在于这些列中的数据?
  2. 你不应该使用int的经度和纬度。 他们应该是在浮动点来代替。


Answer 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


文章来源: Rails Migrations: tried to change the type of column from string to integer