2009-06-30 32 views

Trả lời

48

Tín dụng cho 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 
  • Xem tùy chọn :id => false mà vô hiệu hóa việc tạo ra tự động của các trường id
  • Dòng t.integer :id, :limit => 8 sẽ tạo ra một chút 64 trường số nguyên
+0

Cảm ơn bạn, hoàn hảo !! Hoạt động trong Rails 2.3.11, là tốt. – nessur

+10

Thật không may điều này không tạo cột id làm khóa chính v.v. – gravitystorm

+1

Đúng. Tôi đã làm điều đó với SQL thô. Tôi đã đọc soruce, và tôi không tìm thấy bất kỳ tùy chọn để làm điều đó một cách thông minh (3.0.7). Thật là sự xấu hổ. Nhưng này! 3.1.0 là ra trong một thời gian! Chúc may mắn! – Notinlist

6

Theo tài liệu API Rails, các tùy chọn có thể cho loại hình là:

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

Bạn có thể sử dụng: thập phân, hoặc bạn có thể thực hiện một lệnh trực tiếp nếu bạn cần phải:

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

Như wappos đã chỉ ra, bạn có thể sử dụng các tùy chọn phụ trợ như: giới hạn để báo cho ActiveRecord mức độ lớn mà bạn muốn cột. Vì vậy, bạn sẽ sử dụng cột int: với giới hạn lớn hơn:

+0

"Như wappos chỉ ra, bạn có thể sử dụng tùy chọn phụ trợ như:. Hạn nói ActiveRecord lớn như thế nào bạn muốn cột được Vì vậy, bạn sẽ sử dụng : int cột với một lớn hơn: giới hạn. " Tôi không nghĩ rằng sẽ làm việc nếu những gì ông muốn là lớn hơn số nguyên sẽ giữ. Đặt giới hạn lớn hơn sẽ không thay đổi kích thước tối đa. –

+0

thực tế: primary_key không có tùy chọn giới hạn: do đó, tùy chọn này không hoạt động đối với cột khóa chính. –

+2

Tôi chỉ xem nó trong tài liệu Rails và nếu sử dụng: limit => 8 trên cột số nguyên bạn sẽ nhận được một bigint. Tôi đã không nhận ra rằng. –

7

Điều này khó đặt cho khóa chính bằng di chuyển vì Rails tự động đặt nó.

Bạn có thể thay đổi bất kỳ cột sau như thế này:

change_column :foobars, :something_id, 'bigint'

Bạn có thể chỉ định ID phi chính như các loại tùy chỉnh trong di chuyển ban đầu của bạn như thế này:

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

Nơi tôi có " bigint "bạn có thể đặt bất kỳ văn bản nào mà cơ sở dữ liệu của bạn sẽ sử dụng cho loại cột cơ sở dữ liệu bạn muốn sử dụng (ví dụ:" unsigned long ").

Nếu bạn cần cột id của bạn là một bigint, cách dễ nhất để làm điều đó là tạo bảng, sau đó thay đổi cột trong cùng một di chuyển với change_column.

Với PostgreSQL và SQLite, các thay đổi lược đồ là nguyên tử do đó điều này sẽ không để cơ sở dữ liệu của bạn ở trạng thái lạ nếu quá trình di chuyển không thành công. Với MySQL bạn cần phải cẩn thận hơn.

+0

Cảm ơn - có vẻ như cho một cột "bình thường" bằng cách sử dụng giới hạn => 8 sẽ làm các trick, nhưng đối với primary_key này không hoạt động. Đối với MySQL, bây giờ tôi đã sử dụng SQL tùy chỉnh với thực thi. Muốn change_column, nhưng sẽ không có vấn đề tương tự như tạo ban đầu, cụ thể là: limit => 8 sẽ không được hỗ trợ cho các cột khóa chính? –

+1

Không, bạn có thể sử dụng change_column với khóa chính, như sau: change_column: foobars,: id, "bigint". Vì vậy, bạn sẽ tạo bảng và sau đó ngay lập tức thay đổi cột ID thành bigint. Tôi vẫn không nghĩ rằng bằng cách sử dụng: giới hạn với một cột int sẽ làm việc (với MySQL anyway) bởi vì kích thước tối đa của int là 2 ** 31-1 không có vấn đề gì. –

+1

OK, tôi chỉ xem nó trong tài liệu Rails và nếu bạn làm t.column: foobar,: int,: limit => 8 bạn sẽ nhận được một bigint. –

43

Để đặt loại cột khóa chính mặc định, các tệp di chuyển không phải là nơi gây rối.

Thay vào đó, chỉ cần dính này ở dưới cùng của bạn config/environment.rb

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

Và tất cả các bảng của bạn nên được tạo ra với các loại cột dành cho id:

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

Sau khi bạn đã làm được những gì bạn đã đặt ra để làm ... câu hỏi tiếp theo có lẽ là "Làm cách nào để tôi tạo các cột khóa ngoài cùng loại cột?" vì nó không có ý nghĩa để có khóa chính people.idbigint(20) unsignedperson_idint(11) hoặc bất kỳ điều gì khác?

Đối với các cột đó, bạn có thể tham khảo các đề xuất khác, ví dụ:

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

CẬP NHẬT: @Notinlist, sử dụng cột tùy ý cho khóa chính trên bảng tùy ý bạn cần phải làm như create_table-change_column nhảy:

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

ví dụ nếu tôi muốn guid thay vì số nguyên auto-increment,

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

Đây là một cách tiếp cận hữu ích, nhưng có cách nào để làm cho cơ sở dữ liệu độc lập hoặc chỉ là giá một trả tiền cho nhu cầu này? – brokenbeatnik

+0

có thể là sau. – choonkeat

+1

Điều gì xảy ra nếu tôi không muốn sử dụng 'bigint' cho tất cả các bảng của mình, chỉ dành cho một số? – Notinlist

2

Rails 3, MySQL:

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

Không cho tôi một bigint, chỉ một int. Tuy nhiên,

t.column :twitter_id, 'bigint' 

hoạt động tốt. (Mặc dù nó buộc tôi để MySQL.)

+0

' bigint 'làm loại cột cũng sẽ hoạt động trên PostgreSQL. Tôi đã sử dụng nó vào ngày khác cho một cột int kích thước 8. –

+0

Cool! MySQL và PostgreSQL là những cái duy nhất có vẻ liên quan đến tôi. Trên thực tế, chúng bây giờ thuộc sở hữu của cùng một tổ chức tôi nghe .. – Duke

+1

MySQL hiện thuộc sở hữu của Oracle, nhưng đây không phải là trường hợp của PostgreSQL, có thể có nghĩa là nó sẽ phát triển mạnh hơn :) – m33lky

2

Vay từ các giải pháp khác, được điều chỉnh cho những gì đã làm việc cho tôi gần đây.

Thêm vào tệp trong config/initializers. Nó khai báo một kiểu cột mới (được điều chỉnh theo gợi ý của chookeat).

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

Migrations rằng sử dụng một id dài là như vậy:

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

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

Nếu ai cần này để làm việc với PostgreSQL, tạo ra một khởi tạo như thế này:

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

Do tải chậm trong Rails 3.2 (và thậm chí có thể là các phiên bản cũ hơn), ActiveRecord::ConnectionAdapters::PostgreSQLAdapter sẽ không được yêu cầu cho đến khi bạn thiết lập kết nối cơ sở dữ liệu.

+0

Bạn không cần phải thiết lập kết nối để thực hiện yêu cầu, chỉ cần yêu cầu bộ điều hợp thích hợp, ví dụ: cho pg: yêu cầu 'active_record/connection_adapters/postgresql_adapter', mysql: yêu cầu 'active_record/connection_adapters/abstract_mysql_adapter', sqlite: yêu cầu 'active_record/connection_adapters/sqlite3_adapter', oracle: yêu cầu 'active_record/connection_adapters/oracle_enhanced_adapter'. –

0

Tôi đã viết một viên đá quý được gọi là activerecord-native_db_types_override cho phép bạn thay đổi các kiểu dữ liệu sẽ được sử dụng trong di chuyển của bạn.

Trong Gemfile của bạn, thêm:

gem 'activerecord-native_db_types_override' 

sau đó trong config/environment.rb, sử dụng id dài trong postgres, thêm:

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

Xem README nó cho to-date up- thông tin.

-1

Correction để làm thế nào để thay đổi mặc định loại primary key cột:

Thay vì:

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

bạn nên làm:

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

hoặc nếu không bạn sẽ không thể để thêm foreign key hạn chế trong lớp cơ sở dữ liệu.

+0

Bạn có thể cung cấp thêm chi tiết về sự khác biệt giữa 'BIGINT (** 8 **)' và 'BIGINT', và nó ảnh hưởng như thế nào đến việc tạo khóa ngoài trong MySQL? (Tôi đã thử googling và tìm kiếm tài liệu MySQL, nhưng các ký tự đặc biệt đang borking tìm kiếm.) – MothOnMars

+1

Tôi nghi ngờ OP đã chỉ đặt những dấu hoa thị để nhấn mạnh. Tôi đã chỉnh sửa để xóa chúng. Anh ta cũng sai, BTW - giá trị chính xác cho các con số trong MySQL chỉ ảnh hưởng đến chiều rộng hiển thị của chúng, và không cần thiết cho chúng trong trường hợp này. – SFEley

4

Trong rails4, bạn có thể làm điều đó.

Sau đây là một ví dụ để tạo ra một mô hình Dummy trong 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 

gì nó đã làm:

  • Nó sử dụng serial8 như loại id, là số nguyên 64 bit và xác định nó là primary key.
  • Sử dụng timestamptz làm loại ngày giờ, chứa thông tin múi giờ, điều này quan trọng đối với ứng dụng đi qua nhiều múi giờ.
0

Bạn có thể làm điều đó như thế này:

class CreateUsers < ActiveRecord::Migration[5.0] 
    def change 
    create_table :users, id: :bigserial do |t| 
     t.string :name 
    end 
    end 
end 
Các vấn đề liên quan