2009-06-30 7 views

Respuesta

48

Créditos a http://moeffju.net/blog/using-bigint-columns-in-rails-migrations

class CreateDemo < ActiveRecord::Migration 
    def self.up 
    create_table :demo, :id => false do |t| 
     t.integer :id, :limit => 8 
    end 
    end 
end 
  • Vea la opción :id => false que desactiva la creación automática de campo id
  • La línea t.integer :id, :limit => 8 producirá un poco 64 campo entero
+0

Gracias, perfecto !! Funciona en Rails 2.3.11, también. – nessur

+10

Lamentablemente, esto no crea la columna de identificación como clave principal, etc. – gravitystorm

+1

Es cierto. Lo hice con SQL sin formato. He leído el soruce y no encontré ninguna opción para hacerlo inteligentemente (3.0.7). Es una pena. ¡Pero hey! 3.1.0 está fuera por un tiempo! ¡Buena suerte! – Notinlist

6

De acuerdo con la documentación de la API rieles, las posibles opciones para el tipo son:

:string 
:text 
:integer 
:float 
:decimal 
:datetime 
:timestamp 
:time 
:date 
:binary 
:boolean 

que puede utilizar: decimal, o puede ejecutar un comando directamente si es necesario:

class MyMigration 
    def self.up 
    execute "ALTER TABLE my_table ADD id LONG" 
    end 
end 

Como lo señaló wappos, puede usar opciones auxiliares como: limit para decirle a ActiveRecord qué tan grande quiere que sea la columna. Entonces usaría la columna: int con un límite más grande.

+0

"Como wappos señalaron, puede utilizar las opciones auxiliares como:. Límite para contar ActiveRecord lo grande que desea que la columna sea Así que lo haría con el : columna int con un mayor: límite. " No creo que funcione si lo que quiere es más grande que el número entero. Establecer un límite más grande no cambiará el tamaño máximo. –

+0

de hecho: primary_key no tiene la opción: limit, por lo que esto no funciona para la columna de la clave principal. –

+2

Acabo de buscarlo en los documentos de Rails y si usa: limit => 8 en una columna entera obtendrá un bigint. No me di cuenta de eso. –

7

Esto es difícil de configurar para la clave principal con migraciones porque Rails la coloca automáticamente.

Puede cambiar cualquier columna después de esta manera:

change_column :foobars, :something_id, 'bigint'

Se pueden especificar identificadores no primarios como los tipos personalizados en su migración inicial de esta manera:

create_table :tweets do |t| 
    t.column :twitter_id, 'bigint' 
    t.column :twitter_in_reply_to_status_id, 'bigint' 
end 

Dónde tengo " bigint "puede poner cualquier texto que su base de datos use para el tipo de columna de base de datos que quiera usar (por ejemplo," unsigned long ").

Si necesita que su columna de identificación sea un bigint, la forma más fácil de hacerlo sería crear la tabla, luego cambie la columna en la misma migración con change_column.

Con PostgreSQL y SQLite, los cambios de esquema son atómicos por lo que esto no dejará su base de datos en un estado extraño si la migración falla. Con MySQL necesitas ser más cuidadoso.

+0

Gracias - parece que una columna "normal" que usa limit => 8 haría el truco, pero para primary_key esto no funciona. Para MySQL ahora he usado SQL personalizado con execute. Preferiría change_column, pero ¿no tendría el mismo problema que la creación inicial, concretamente que: limit => 8 no sería compatible con las columnas de clave primaria? –

+1

No, puede usar change_column con la clave principal, así: change_column: foobars,: id, "bigint". Entonces crearías la tabla y luego cambiarías inmediatamente la columna ID para que sea una letra grande. Todavía no creo que usar: limit con una columna int va a funcionar (con MySQL de todos modos) porque el tamaño máximo de int es 2 ** 31-1 sin importar qué. –

+1

OK, acabo de buscarlo en los documentos de Rails y si lo hace t.column: foobar,: int,: limit => 8 obtendrá un bigint. –

43

Para configurar columna de clave primaria predeterminada tipo, los archivos de migración no son el lugar para meterse.

En su lugar, sólo se adhieren esto en la parte inferior de su config/environment.rb

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY" 

Y todas las tablas deben crearse con el tipo de columna destinada a id:

+--------------+---------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+--------------+---------------------+------+-----+---------+----------------+ 
| id   | bigint(20) unsigned | NO | PRI | NULL | auto_increment | 

Después de haber hecho lo se ha propuesto ... la próxima pregunta es, probablemente, "¿Cómo puedo hacer que mis columnas de clave externa tengan el mismo tipo de columna?" ya que no tiene sentido tener la clave principal people.id como bigint(20) unsigned, y person_id ser int(11) o cualquier otra cosa?

Para esas columnas, puede consultar otras sugerencias, p. Ej.

t.column :author_id, 'BIGINT UNSIGNED' 
t.integer :author_id, :limit => 8 

ACTUALIZACIÓN: @Notinlist, para usar la columna arbitraria de clave principal en tablas arbitrarias que tiene que hacer el baile create_table-change_column:

create_table(:users) do |t| 
    # column definitions here.. 
end 
change_column :users, :id, :float # or some other column type 

por ejemplo, si quería guid en lugar de números enteros de incremento automático,

create_table(:users, :primary_key => 'guid') do |t| 
    # column definitions here.. 
end 
change_column :users, :guid, :string, :limit => 36 
+1

Este es un enfoque útil, pero ¿hay alguna manera de hacer que esta base de datos sea independiente o es solo el precio que uno paga por esta necesidad? – brokenbeatnik

+0

probablemente el último. – choonkeat

+1

¿Qué pasa si no quiero usar 'bigint' para todas mis tablas, solo para algunos? – Notinlist

2

Rails 3, MySQL:

t.column :foobar, :int, :limit => 8 

no me da un bigint, solamente un int. Sin embargo,

t.column :twitter_id, 'bigint' 

funciona bien. (A pesar de que hace atarme a MySQL.)

+0

'bigint' como tipo de columna también debería funcionar en PostgreSQL. Lo usé el otro día para una columna int de tamaño 8. –

+0

¡Genial! MySQL y PostgreSQL son los únicos que me parecen relevantes. En realidad, ahora son propiedad de la misma organización que escuché ... – Duke

+1

MySQL ahora es propiedad de Oracle, pero este no es el caso de PostgreSQL, lo que probablemente significa que prosperará más :) – m33lky

2

Tomando prestado de otras soluciones, ajustado por lo que funcionó para mí recientemente.

Agregar a un archivo en config/initializers. Declara un nuevo tipo de columna (adaptado de la sugerencia de chookeat).

ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"

migraciones que utilizan mucho ID son como tal:

create_table :notification_logs, :id => false do |t| 

     t.column :id, :long_primary_key 
     # ... 
    end 
5

Si alguien necesita esto para trabajar con PostgreSQL, crear un inicializador de esta manera:

# config/initializers/bigint_primary_keys.rb 
ActiveRecord::Base.establish_connection 
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key' 

Debido No se requerirá la carga diferida en Rails 3.2 (y tal vez incluso en versiones anteriores), ActiveRecord::ConnectionAdapters::PostgreSQLAdapter hasta que establezca la conexión de la base de datos.

+0

No es necesario que establezca una conexión para hacer lo necesario, solo necesita el adaptador adecuado, p. para pg: requiere 'active_record/connection_adapters/postgresql_adapter', mysql: require 'active_record/connection_adapters/abstract_mysql_adapter', sqlite: require 'active_record/connections_adapters/sqlite3_adapter', oracle: require 'active_record/connection_adapters/oracle_enhanced_adapter'. –

0

Escribí una gema llamada activerecord-native_db_types_override que le permite alterar los tipos de datos que se utilizarán en sus migraciones.

En su Gemfile, añadir:

gem 'activerecord-native_db_types_override' 

continuación, en config/environment.rb, al utilizar identificadores largos en Postgres, añadir:

NativeDbTypesOverride.configure({ 
    postgres: { 
    primary_key: { name: "bigserial primary key"} 
    } 
}) 

Ver su README para arriba-hasta la fecha información

-1

Corrección de cómo cambiar el tipo predeterminado primary key columna:

En lugar de:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY" 

que debe hacer:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY" 

o de lo contrario no será capaz de añadir foreign key restricciones en la capa de la base de datos.

+0

¿Podría proporcionar más detalles sobre la diferencia entre 'BIGINT (** 8 **)' y 'BIGINT', y cómo afecta la creación de claves externas en MySQL? (Intenté buscar en Google y buscar en la documentación de MySQL, pero los caracteres especiales están bloqueando la búsqueda.) – MothOnMars

+1

Sospecho que el OP solo estaba poniendo esos asteriscos para enfatizar. Edité para eliminarlos. También está equivocado, BTW: los valores de precisión para los números en MySQL solo afectan su ancho de visualización, y no es necesario en este caso. – SFEley

4

En rails4, puede hacerlo.

siguiente es un ejemplo para crear un modelo Dummy en rails4 & postgres,

xxx_migrate_dummies.rb:

class CreateDummies < ActiveRecord::Migration 
    def change 
    create_table :dummies, :id => false do |t| 
     t.column :id, :serial8, primary_key: true 
     t.string :name, :limit => 50, null: false 
     t.integer :size, null: false 

     t.column :create_date, :timestamptz, null: false 
    end 
    end 
end 

Lo que hizo:

  • Se utilizan serial8 como tipo de id., que es un entero de 64 bits, y defínalo como primary key.
  • Utiliza timestamptz como tipo de fecha y hora, que contiene la información de la zona horaria, esto es importante para una aplicación que atraviesa varias zonas horarias.
0

Puede hacerlo de esta manera:

class CreateUsers < ActiveRecord::Migration[5.0] 
    def change 
    create_table :users, id: :bigserial do |t| 
     t.string :name 
    end 
    end 
end 
Cuestiones relacionadas