使用预设 ID 播种 Rails 数据库

发布于 2024-08-31 01:52:17 字数 1747 浏览 6 评论 0原文

我有一个包含种子数据的 XML 文件,我正在尝试将其加载到生产数据库中。

问题是我在 XML 文件中的不同数据类型/节点之间存在关联,因此当从 Rails 加载到 MySQL 中时,我需要指定的 ID 相同。

这在开发过程中与 SQLite 配合得很好,我只是在迭代 XML 文件中的每个节点后使用如下一行:

CardSet.connection.execute("UPDATE card_sets SET id = #{xml_set.attributes['id']} WHERE id = #{set.id}")

我的问题是:如何在播种数据库时强制预设 ID,然后能够重新打开 auto_increment 以使 Rails 正常运行吗?

在创建数据库条目之前,我已经尝试使用这两行:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL")
CardSet.connection.execute("ALTER TABLE card_sets DROP PRIMARY KEY")

以及之后的内容:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY")

MySQL 向我返回如下:

Mysql::Error: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '18' for key 'PRIMARY': ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY

我的架构:

create_table "card_sets", :force => true do |t|
  t.string   "name"
  t.datetime "created_at"
  t.datetime "updated_at"
end

create_table "card_sets_cards", :id => false, :force => true do |t|
  t.integer "card_set_id"
  t.integer "card_id"
end

create_table "cards", :force => true do |t|
  t.text     "question",   :default => ""
  t.text     "answer",     :default => ""
  t.datetime "created_at"
  t.datetime "updated_at"
end

和模型:

class CardSet < ActiveRecord::Base
  has_and_belongs_to_many :cards, :uniq => true
end

class Card < ActiveRecord::Base
    has_and_belongs_to_many :card_set, :uniq => true
end

任何想法将不胜感激。

I have an XML file containing seed data that I'm trying to load into my production database.

The problem being that I have associations between different data types / nodes in the XML file, and so I need the specified IDs to be the same when loaded into MySQL from Rails.

This works fine with SQLite during development, I just use a line like the one below after iterating through each node in the XML file:

CardSet.connection.execute("UPDATE card_sets SET id = #{xml_set.attributes['id']} WHERE id = #{set.id}")

My question is: how can I force pre-set IDs when seeding the database, and then be able to turn auto_increment back on for Rails to function as normal?

I've attempted this with these two lines before creating the database entry:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL")
CardSet.connection.execute("ALTER TABLE card_sets DROP PRIMARY KEY")

and this after:

CardSet.connection.execute("ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY")

which MySQL fires back to me as:

Mysql::Error: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '18' for key 'PRIMARY': ALTER TABLE card_sets CHANGE id id INT(11) DEFAULT NULL auto_increment PRIMARY KEY

My schema:

create_table "card_sets", :force => true do |t|
  t.string   "name"
  t.datetime "created_at"
  t.datetime "updated_at"
end

create_table "card_sets_cards", :id => false, :force => true do |t|
  t.integer "card_set_id"
  t.integer "card_id"
end

create_table "cards", :force => true do |t|
  t.text     "question",   :default => ""
  t.text     "answer",     :default => ""
  t.datetime "created_at"
  t.datetime "updated_at"
end

And models:

class CardSet < ActiveRecord::Base
  has_and_belongs_to_many :cards, :uniq => true
end

class Card < ActiveRecord::Base
    has_and_belongs_to_many :card_set, :uniq => true
end

Any ideas would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的心境我的脸 2024-09-07 01:52:17

我解决 MySQL 错误的方法是正常创建模型实例 (CardSet.create),然后强制更新 ID,然后重新加载实例:

c = CardSet.create(...blah....)
CardSet.connection.execute("UPDATE card_sets SET id = #{real_card_set_id} WHERE id = #{c.id}")
c = CardSet.find(real_card_set_id)
c.save!

My way around the MySQL error was to create the model instance normally (CardSet.create), and then force an update to the ID, and then reload the instance:

c = CardSet.create(...blah....)
CardSet.connection.execute("UPDATE card_sets SET id = #{real_card_set_id} WHERE id = #{c.id}")
c = CardSet.find(real_card_set_id)
c.save!
平安喜乐 2024-09-07 01:52:17

如果您以块形式创建对象,它就会起作用。

p = Post.new do |post|
  post.id = 1000
end

p.save

If you create your objects in block form, it'll work.

p = Post.new do |post|
  post.id = 1000
end

p.save
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文