【问题标题】:How to use ActiveRecord to force a foreign key in SQLite3?如何使用 ActiveRecord 在 SQLite3 中强制使用外键?
【发布时间】:2017-07-28 07:00:31
【问题描述】:

SQLite3 不允许将现有表的列设置为外键,但在创建新表时确实允许这样做,但是当我打开 .sqlite3 文件时,这段代码似乎没有创建具有外键的表?

class CreateProducts < ActiveRecord::Migration[5.0]
  def change
    create_table :products do |t|
      t.string :name
      t.text :description
      t.float :cost
      t.references :category, foreign_key: true

      t.timestamps
    end
  end
end

当我在 SQLite 数据库浏览器中单击“产品”时,我希望它会在架构中的“产品”旁边显示以下内容:

CREATE TABLE `products` (
    `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    `name`  varchar,
    `description`   text,
    `cost`  float,
    `category_id`   integer,
    `created_at`    datetime NOT NULL,
    `updated_at`    datetime NOT NULL,
    FOREIGN KEY(`category_id`) REFERENCES categories ( id )
);

相反,架构在“产品”旁边有以下内容:

CREATE TABLE `products` (
    `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    `name`  varchar,
    `description`   text,
    `cost`  float,
    `category_id`   integer,
    `created_at`    datetime NOT NULL,
    `updated_at`    datetime NOT NULL,
);

那么如何使迁移强制 .sqlite3 文件具有外键?

即使我手动编辑 .sqlite3 文件以在产品和类别之间包含外键,products_controller.rb 中的以下代码仍返回 false、false 和 true。

@current_connection = Product.connection
puts @current_connection.foreign_key_exists?(:categories, :products)
puts @current_connection.foreign_key_exists?(:products, :categories)
puts @current_connection.index_exists?(:products, :category_id)

如果使用的是.sqlite3,为什么输出为假一真?

另外,PostgreSQL 表在创建产品的迁移运行时是否会有外键,还是会出现同样的问题?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord sqlite


    【解决方案1】:

    试试这个

    class CreateProducts < ActiveRecord::Migration[5.0]
      def change
        create_table :products do |t|
          t.string :name
          t.text :description
          t.float :cost
          t.references :category, foreign_key: true
          add_foreign_key :products, :categories, foreign_key: true
    
          t.timestamps
        end
      end
    end
    

    结果:

    CREATE TABLE "products" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "description" text, "cost" float, "category_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
    CREATE INDEX "index_products_on_category_id" ON "products" ("category_id");
    

    【讨论】:

    • 如何使 Somemodel.connection.foreign_key_exists?(:tablea, :tableb) 返回 true?
    • 那么 ActiveRecord 隐式 在运行创建表迁移后是否有外键,但不会将它们存储在使用的任何 dbms 上?如果是这样,foreign_key_exists 可以吗?曾经返回 true 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多