mysql2::错误:指定的密钥太长;对于只有87 db字段的表,最大密钥长度为767字节

31moq8wy  于 2021-06-17  发布在  Mysql
关注(0)|答案(3)|浏览(828)

我有一个包含87个db列的rails模型,但是当我尝试添加任何额外的db列时,它失败了

  1. ArbitaryDatum.columns.count
  2. => 87
  3. ArbitaryDatum.table_name
  4. => "arbitary_data"
  5. ActiveRecord::Migration.add_column :arbitary_data, :attr51, :string
  6. -- add_column(:arbitary_data, :attr51, :string)
  7. (1.4ms) ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
  8. Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
  9. ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)

我检查了我使用的mysql版本,

  1. mysql --version
  2. mysql Ver 14.14 Distrib 5.5.62, for debian-linux-gnu (i686) using readline 6.3

我不明白为什么它不允许添加额外的表列
问。为什么我不能 Mysql2::Error: Specified key was too long

v64noz0r

v64noz0r1#

将数据库创建为utf8\u general\u ci,这样就没有问题了

8fq7wneg

8fq7wneg2#

在为这个问题奋斗了三天之后,@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

  1. 在中运行上述代码时 `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)

  1. 所以我找到了它不允许为现有索引添加新列->无效名称的原因。
  2. 所以我删除了索引,然后我可以添加新的列。

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

  1. 使用帮助再次添加了相同的索引
展开查看全部
w6lpcovy

w6lpcovy3#

mysql在innodb中的前缀限制为767字节,在myisam中的前缀限制为1000字节,
不幸的是,没有真正的解决办法。您唯一的选择是减小列的大小,使用不同的字符集(如utf-8),或者使用不同的引擎(如myisam)。在本例中,我将字符集切换为utf-8,从而将最大密钥长度提高到255个字符。
将字符集迁移为utf8

  1. reversible do |dir|
  2. dir.up {
  3. ActiveRecord::Migration.add_column :data, :attr51, "VARCHAR(255) CHARACTER SET utf8"
  4. }
  5. end

相关问题