如何在Ruby on Rails中创建一个类型为tinyint(2)或tinyint(3)的列?

17
在Ruby on Rails中,下面的代码可以在MySQL中创建一个tinyint(4)类型的列:
create_table :great_table do |t|
    t.integer :step_position, :limit => 1 #tinyint
end

我要创建一个类型为tinyint(2)tinyint(3)的列,该怎么做?


2
我不建议你一开始就使用 tinyint。它过于具体化。我敢说,实际上使用普通整数字段的性能可能比它还要差。它可能会为每个记录节省一些微不足道的空间,但我甚至不确定这是否属实。我认为你很难说服我有理由使用它。 - Jim Stewart
4个回答

23

对于tinyint(2)

create_table :great_table do |t|
  t.integer :step_position, :limit => 2
end

对于tinyint(3)数据类型:

create_table :great_table do |t|
  t.integer :step_position, :limit => 3
end

这并不创建tinyints。根据定义,tinyint使用1个字节进行存储。在这里,您正在使用2个字节(smallint)和3个字节(mediumint)。 https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html - TanguyP

12

根据我在宝石源代码中所看到的内容,你无法:

     # File activerecord/lib/active_record/connection_adapters/mysql_adapter.rb, line   540  
     540:       def type_to_sql(type, limit = nil, precision = nil, scale = nil)
     541:         return super unless type.to_s == 'integer'
     542: 
     543:         case limit
     544:         when 1; 'tinyint'
     545:         when 2; 'smallint'
     546:         when 3; 'mediumint'
     547:         when nil, 4, 11; 'int(11)'  # compatibility with MySQL default
     548:         when 5..8; 'bigint'
     549:         else raise(ActiveRecordError, "No integer type has byte size #{limit}")
     550:         end
     551:       end

type_to_sql


不确定这段代码是否相关;超类中有什么内容?迁移确实支持:tinyint类型。当同时指定:integer:limit时,这段代码是Rails决定忽略你的:integer类型规范并使用替代类型来表示更小/更大的整数值的地方。 - Jim Stewart
你可能错了,type_to_sql是从add_column中调用的。你可以在代码中看到:http://api.rubyonrails.org/v2.3.8/classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html#M001549 - FedeX
我认为我可能错了,关于第一位有任何tinyint类型的支持(除了间接由于整数和限制组合)。当类型为整数时,上面的代码肯定会被应用。 - Jim Stewart

5

MySQL中根本不存在tinyint(4)这种类型。 tinyint是一种占用一个字节的有符号整数。您可以在文档中查看所有整数类型。即使在Rails 源代码中,您可能也会看到类似tinyint(1)的内容,但我认为这是一种同义反复,因为tinyint已经暗示了一个字节的存储。

在迁移中声明TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT的Rails方法是使用适当的字节大小作为limit:,可以在源代码中看到。请注意,默认情况下,Rails会将一字节整数视为布尔值,如上面的链接所示。

2
实际上,括号中的数字与存储所使用的字节数无关。它只是指定了一个显示宽度,显示这个数字的应用程序可能会选择遵守或不遵守。 - TanguyP

1
你可以在Rails迁移中使用:tinyint作为列类型,并像之前所述写limit: 2limit: 3
以您的示例为例:
create_table :great_table do |t|
    t.tinyint :step_position, :limit => 1
end

应该可以工作。

2
嘿,伙计,你不能在迁移中使用tinyint,实际上应该使用integer并限制为1。 - Gagan
1
@Gagan 如果提供 add_column :table_name, :column_name, :tinyint 没有引发任何异常并且迁移过程似乎非常顺利。我可以想象 t.tinyint 也是以同样的方式工作的。不过这可能是因为较新的版本,我已经在 Ruby on Rails 5.1 中测试了添加 tinyint 列。 - 3limin4t0r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接