简体   繁体   English

SQLite迁移从schema.rb文件中删除了“ add_index”和“ add_foreign_key”

[英]SQLite migration removes 'add_index' and 'add_foreign_key' from schema.rb file

I use SQLite3 and MySQL on the same Rails project but on two different computers. 我在同一Rails项目上但在两台不同的计算机上使用SQLite3和MySQL。 I noticed that the schema.rb which is generated when I run all migrations looks different for both environments. 我注意到,在我运行所有迁移时生成的schema.rb在两种环境下看起来都不同。 When I run the migrations in the SQLite3 environment the following statements are removed from the schema.rb file. 当我在SQLite3环境中运行迁移时,以下语句已从 schema.rb文件中删除

add_index "places", ["user_id"], :name => "places_user_id_fk"
add_foreign_key "places", "users", :name => "places_user_id_fk"

Please note, that I use the foreigner gem which extends migrations with add_foreign_key and remove_foreign_key . 请注意,我使用的外国人gem通过add_foreign_keyremove_foreign_key扩展了迁移。

Here are the migrations and model relevant to the problem: 以下是与问题相关的迁移和模型:

# 20130123004056_create_places.rb
class CreatePlaces < ActiveRecord::Migration
  def change
    create_table :places do |t|
      t.string :name
      t.string :location
      t.integer :user_id
      t.timestamps
    end
  end
end

... ...

# 20130123234250_add_foreign_key.rb
class AddForeignKey < ActiveRecord::Migration
  def change
    add_foreign_key(:places, :users)
  end
end

... ...

# user.rb
class User < ActiveRecord::Base
  has_many :places
end

... ...

# place.rb
class Place < ActiveRecord::Base
  belongs_to :user    
end

Question: How can I define the relationship between users and places in a way both SQLite3 and MySQL can handle it? 问题:如何以SQLite3和MySQL都可以处理的方式定义usersplaces之间的关系?

The foreigner README clearly states foreigner README明确指出

The following adapters are supported: 支持以下适配器:

  • sqlite (foreign key methods are a no-op) sqlite (外键方法是禁止操作的)

So your SQLite database does not have foreign key constraints set up because foreigner doesn't support them . 因此您的SQLite数据库没有设置外键约束, 因为foreigner不支持它们 When db/schema.rb is generated from the SQLite database, this is why there are no foreign keys specified. 从SQLite数据库生成db/schema.rb ,这就是为什么未指定外键的原因。

The Rails Guide on Migrations mentions foreign keys quite a bit Rails迁移指南》中提到了很多外键

If you need to perform tasks specific to your database (for example create a foreign key constraint) then the execute method allows you to execute arbitrary SQL 如果您需要执行特定于数据库的任务(例如,创建外键约束),那么execute方法允许您执行任意SQL

There is even an example of how to add/remove a foreign key . 甚至还有一个有关如何添加/删除外键的示例。

Having used foreigner when first starting out with Rails, I suggest you drop it from your Gemfile and either 刚开始使用Rails时曾使用过foreigner ,建议您将其从Gemfile ,或者

  1. Don't use foreign keys at all; 完全不要使用外键; just specify your cascades on your ActiveRecord associations 只需在ActiveRecord关联上指定级联
  2. Use the execute migration method as described in the linked example above (and just make sure all the different RDBMS' support whatever you put into the execute methods) 使用上面的链接示例中所述的execute迁移方法(并确保所有不同的RDBMS都支持您在execute方法中添加的内容)
  3. Stop using SQLite in development if you insist on using foreign keys. 如果您坚持使用外键,请停止在开发中使用SQLite。 You're not going to use SQLite in production anyway, and are already using better RDMS (MySQL, "better" in the sense that it has the foreign key support you are looking for) on other machines. 无论如何,您都不会在生产中使用SQLite,并且已经在其他机器上使用了更好的RDMS(MySQL,“更好”,因为它具有正在寻找的外键支持)。

As you pointed out in the comments, SQLite has lacking support for adding foreign keys after the table has been created; 正如您在评论中所指出的那样 ,SQLite在创建表后缺乏对添加外键的支持; they cannot be added through a futre migration in Rails. 无法通过在Rails中进行进一步迁移来添加它们。 I personally suggest you use choice 1 or 3 , as it is going to be more difficult to create a solution through execute commands in migrations that satisfies the restrictions of SQLite while having the same end result on other RDMS'. 我个人建议您使用选择1或3 ,因为在满足SQLite限制的迁移中通过execute命令创建解决方案将更加困难,而在其他RDMS上具有相同的最终结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM