2012-03-02 16 views
19

Tengo un modelo con una columna del tipo integer que quiero convertir al tipo string. Ahora estoy buscando la mejor manera de cambiar el tipo de columna sin perdiendo los datos. ¿Hay una manera indolora de lograr esto?Rieles: cambie el tipo de columna, pero guarde los datos

+1

¿Es éste un hecho aislado, o les gustaría que en repetidas ocasiones funciona, por ejemplo, en una migración? –

Respuesta

33

Una migración estándar utilizando el método change_column convertirá enteros en cadenas sin pérdida de datos. rake db: rollback también hará la migración inversa sin error si es necesario.

Aquí es la migración de prueba he usado para confirmar este comportamiento:

class ChangeAgeToString < ActiveRecord::Migration 
    def self.up 
    change_column :users, :age, :string 
    end 

    def self.down 
    change_column :users, :age, :integer 
    end 
end 
+0

Por alguna razón, eso no funciona para mí. Estoy usando rails 3.2.13 con mysql 14.14 en una Mac, y la migración anterior cambia todos mis valores enteros a 0 – gardenofwine

+1

Acabo de volver a probar con las versiones que mencionaste (Rails 3.2.13 y mysql Ver 14.14 Distrib 5.5.27, para osx10.8 (i386) usando readline 5.1). Todo funcionó como se esperaba. Antes de la migración (=> # ) después de la migración (=> # ). ¿Qué hiciste diferente gardenofwine? – Jon

+0

Estoy experimentando algo similar a @gardenofwine pero convirtiendo la columna de 'time' a' datetime'. Si los datos originales son "09:30:30", después de la migración obtengo todos los ceros. Estoy usando Rails 3.2.12 y la misma versión de mysql que @Jon. Alguna idea de cómo puede suceder esto. – elhoyos

2

Si se trata de un hecho aislado que sólo puede cambiar el tipo de columna en la base de datos (ya que ninguna información se pierde en movimiento de int a varchar)

Para MySQL, esto lo haría:

ALTER TABLE t1 MODIFY col1 VARCHAR(256) 

Si está usando SQLite no tendrá que hacer nada.

+0

¡Utilizo postgresql en el proyecto actual y también funcionó! Gracias por su respuesta, configuré la siguiente publicación como la respuesta aceptada solo porque creo que la mayoría de los usuarios que tienen esta pregunta pueden necesitar una migración. – blissini

+0

Cool. Sí, la respuesta de migración es la mejor. En realidad estaba trabajando, trabajando en un DB de MySql en ese momento, ¡así que la respuesta de la base de datos se me apareció primero! –

3

para postgres en la migración

change_column :table_name, :field,'boolean USING (CASE field WHEN \'your any string as true\' THEN \'t\'::boolean ELSE \'f\'::boolean END)' 

y para cualquier tipo válido similares

1

Si utiliza Postgres, no puede convertir implícitamente una cadena en un entero, por lo que la forma de hacer que el cambio sea reversible es:

class ChangeAgeToString < ActiveRecord::Migration 
    def self.up 
    change_column :users, :age, :string 
    end 

    def self.down 
    add_column :age_integer 
    User.connection.execute('UPDATE users SET age_integer = cast(age as int)') 
    remove_column :users, :age 
    rename_column :users, :age_integer, :age 
    end 
end 
0

para PostgreSQL, mesa de cambio de la columna tipo de datos integer a string,
rails migration like this with up and down actions

class ChangeAgeToString < ActiveRecord::Migration 
    def self.up 
    change_column :users, :age, 'varchar USING CAST(age AS varchar)', null: false 
    end 

    def self.down 
    change_column :users, :age, 'integer USING CAST(age AS integer)', null: false, default: 0 
    end 
end 
Cuestiones relacionadas