【问题标题】:KNEX & MYSQL - Error: ER_CANNOT_ADD_FOREIGN: Cannot add foreign key constraintKNEX 和 MYSQL - 错误:ER_CANNOT_ADD_FOREIGN:无法添加外键约束
【发布时间】:2019-07-27 18:50:04
【问题描述】:

我正在将单体架构重构为微服务,并将其中一个的数据库切换到 MySQL。我正在使用 knex.js 来清理查询。我需要建立3个表。其中一个表只有三列:它自己的 id 和两个外键 id:其他两个表中的每一个。

在尝试构建 knex.js 查询以构建表时,我在标题中收到错误。

我尝试使用可以对 knex.js 查询进行的各种修改来重新安排我的查询,并尝试使用原始 mysql 外键查询。错误仍然存​​在。这是我的js代码:

const knex = require('knex') (CONFIG);

// Build images table
const imagesSchema = () => {
  knex.schema.createTable('images', (table) => {
    table.integer('id').primary();
    table.string('name');
    table.string('src');
    table.string('alt');
    table.string ('category');
    table.string('subCategory');
  })
  .then(console.log('test'));
};

// Build users table
const usersSchema = () => {
  knex.schema.createTable('users', table => {
    table.increments('id').primary();
    table.string('session', 64).nullable();
  })
  .then(console.log('users schema built into DB!'))
  .catch( error => {console.log('cant build the users schema!\n', error)})
}

// Build userhistory table
const userHistorySchema = () => {
  knex.schema.createTable('userhistory', table => {
    table.increments('id').primary();
    table.integer('userid').nullable();
    table.integer('imageid').nullable();

    // add foreign keys:
    table.foreign('userid').references('users.id');
    table.foreign('imageid').references('images.id');
  })
  .then(console.log('userhistory schema built into DB!'))
  .catch( error => {console.log('cant build the userhistory schema!\n', error)})
}

我希望创建表时 userhistory.userid 列指向 users.id 列,userhistory.imageid 列指向 images.id 列。相反,我收到此错误:

Error: ER_CANNOT_ADD_FOREIGN: Cannot add foreign key constraint

code: 'ER_CANNOT_ADD_FOREIGN',
  errno: 1215,
  sqlMessage: 'Cannot add foreign key constraint',
  sqlState: 'HY000',
  index: 0,
  sql: 'alter table `userhistory` add constraint `userhistory_userid_foreign` foreign key (`userid`) references `users` (`id`)'

这些表是在没有外键的情况下创建的。

【问题讨论】:

    标签: javascript mysql knex.js


    【解决方案1】:

    对于 MySQL,外键需要定义为 unsigned()
    所以你的userhistory 架构需要这样设置:

    knex.schema.createTable('userhistory', table => {
        table.increments('id').primary();
        table.integer('userid').unsigned().nullable();
        table.integer('imageid').unsigned().nullable();
    
        // add foreign keys:
        table.foreign('userid').references('users.id');
        table.foreign('imageid').references('images.id');
      })
      .then(console.log('userhistory schema built into DB!'))
      .catch( error => {console.log('cant build the userhistory schema!\n', error)})
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用 Knex 创建表,您可能应该使用 Knex 的迁移引擎,而不是自己滚动引擎。但是,您的问题是,当您尝试创建链接表时,尚未创建具有主键的两个表。这是因为您没有嵌套 createTable 方法的回调。

      我会把它改写成这样的:

      exports.up = async function (knex, Promise) => {
      
        await knex.schema.createTable('images', (table) => {
          table.integer('id').primary();
          table.string('name');
          table.string('src');
          table.string('alt');
          table.string ('category');
          table.string('subCategory');
        });
      
        await knex.schema.createTable('users', table => {
          table.increments('id').primary();
          table.string('session', 64).nullable();
        });
      
        await knex.schema.createTable('user_history', table => {
          table.increments('id').primary();
          table.integer('userid').nullable();
          table.integer('imageid').nullable();
      
          table.foreign('userid').references('users.id');
          table.foreign('imageid').references('images.id');
        });
      
      };
      
      exports.down = async function (Knex, Promise) => {
        await knex.dropTable('user_history');
        await knex.dropTable('images');
        await knex.dropTable('users');
      };
      

      请注意,我没有使用回调,而是切换到异步/等待语法,这使得它看起来更像同步代码。这应该更容易理解,因为回调似乎让你绊倒了。在这个例子中,当 Node 尝试运行 await knex.schema.createTable 时,它会暂停并等待表被创建,而不是跳转到下一条语句。这将确保您的 imagesusers 表存在。

      为了做到这一点,您必须使用 Knex 的迁移引擎。如果您不熟悉迁移,请查看 this documentation

      在您的项目目录(knexfile.js 所在的位置)中运行这些命令:

      1. npm install -g knex
      2. knex migrate:make <your_migration_name>
      3. knex migrate:latest

      您应该得到一个绿色的控制台输出,说明它如何成功运行迁移。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-02
        • 2018-04-28
        相关资源
        最近更新 更多