我的Rails模型具有87个db列的表,但是当我尝试添加任何额外的db列时,它失败了
ArbitaryDatum.columns.count
=> 87
ArbitaryDatum.table_name
=> "arbitary_data"
ActiveRecord::Migration.add_column :arbitary_data, :attr51, :string
-- add_column(:arbitary_data, :attr51, :string)
(1.4ms) ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
我检查了我正在使用哪个mysql版本,
mysql --version
mysql Ver 14.14 Distrib 5.5.62, for debian-linux-gnu (i686) using readline 6.3
我不明白为什么不允许添加额外的表格列
问。为什么我没有得到Mysql2::Error: Specified key was too long
答案 0 :(得分:1)
为此问题苦苦挣扎了3天后, @muistooshort 在评论中说的一件事使我朝着正确的解决方法迈进。
您可能想在他的评论中重新访问数据库设计,困扰了我几天。所有需要的都是正确的方向(在那条评论中),我解决了这个问题。
注意:所提供的数据很少进行处理以隐藏项目架构。
我在添加新列时遇到问题,如错误日志所述,但这不是由于在表中添加了新列。这是由于数据库中存在现有的表结构。
我知道何时从config/schema.rb
复制表架构以及索引,以创建相同的新表arbitary_data_dup
# replaced `arbitary_data` with `arbitary_data_dup`
ActiveRecord::Migration.create_table "arbitary_data_dup", force: :cascade do |t|
# code to add 87 columns for table
end
# following index threw error
ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1", "arbitary_structure_id"], name: "index_arbitary_data_on_attr1_and_arbitary_structure_id", unique: true, using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1"], name: "index_arbitary_data_on_attr1", length: {"attr1"=>191}, using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["id"], name: "index_arbitary_data_on_id", using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["arbitary_structure_id"], name: "index_arbitary_data_on_arbitary_structure_id", using: :btree
在上述rails console
中的代码上运行时,它抛出了相同的错误,并且我确定是出于什么原因不允许添加新列,
ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1", "arbitary_structure_id"], name: "index_arbitary_data_on_attr1_and_arbitary_structure_id", unique: true, using: :btree
-- add_index("arbitary_data_dup", ["attr1", "arbitary_structure_id"], {:name=>"index_arbitary_data_on_attr1_and_arbitary_structure_id", :unique=>true, :using=>:btree})
(52.5ms) CREATE UNIQUE INDEX `index_arbitary_data_on_attr1_and_arbitary_structure_id` USING btree ON `arbitary_data_dup` (`attr1`, `arbitary_structure_id`)
Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX `index_arbitary_data_on_attr1_and_arbitary_structure_id` USING btree ON `arbitary_data_dup` (`attr1`, `arbitary_structure_id`)
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX `index_arbitary_data_on_attr1_and_arbitary_structure_id` USING btree ON `arbitary_data_dup` (`attr1`, `arbitary_structure_id`)
所以我找到了不允许添加新列的原因->现有索引的名称无效。
因此我删除了该索引,之后便可以添加新列。
ActiveRecord::Migration.remove_index "arbitary_data", ["attr1", "arbitary_structure_id"]
-- remove_index("arbitary_data", ["attr1", "arbitary_structure_id"])
(148.6ms) DROP INDEX `index_arbitary_data_on_attr1_and_arbitary_structure_id` ON `arbitary_data`
-> 0.1698s
=> nil
ActiveRecord::Migration.add_column :arbitary_data, :attr51, :string
-- add_column(:arbitary_data, :attr51, :string)
(523.3ms) ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
-> 0.5238s
=> nil
使用help
再次添加了相同的索引答案 1 :(得分:0)
MySQL在InnoDB中的前缀限制为767个字节,在MYISAM中为1000个字节,
不幸的是,对此没有真正的解决方案。您唯一的选择是减小列的大小,使用其他字符集(例如UTF-8)或使用其他引擎(例如MYISAM)。在这种情况下,我将字符集切换为UTF-8,这将最大密钥长度增加到255个字符。
在“迁移”中,将字符集设置为UTF8
reversible do |dir|
dir.up {
ActiveRecord::Migration.add_column :data, :attr51, "VARCHAR(255) CHARACTER SET utf8"
}
end
答案 2 :(得分:0)
将数据库创建为utf8_general_ci,然后没问题