knex.js 迁移创建彼此之间有关系的表失败

knex.js migrations create tables with relationship between each other fails

我找遍了所有地方,有很多示例,但没有一个是完整的或有效的。

用例: 简单的数据库结构,几个 table 和一些关系。在 docker 容器中设置节点、knex 和 pg。 一切正常。 为第一个 table (table A) 创建了迁移文件 - 好的。 添加了第二个 table (table B) 和从 table B 到 A 的 1:n 关系。一切都很好。 添加了从 table A 到 table B 的 1:n 关系。脚本出错了。

table 信息:

exports.up = function(knex) {
  return knex.schema
    .createTable('user', t => {
      t.uuid('user_id').primary()
      t.string('name', 100).notNullable()
      t.string('surname', 100)
      t.string('email').notNullable().unique()
      t.string('password')
      t
        .boolean('email_confirmed')
        .notNullable()
        .defaultTo(false)
      t
        .datetime('last_login', { precision: 6 })
        .defaultTo(knex.fn.now(6))
      t.string('language')
      t.string('newsletter')
      t.timestamps(true, true)
      t
        .uuid('company_id')
        .references('company_id')
        .inTable('company')
  })
  .createTable('company', t => {
    t.uuid('company_id').primary()
    t.string('address_id')
    t.string('name', 100).notNullable()
    t.string('phone')
    t.timestamps(true, true)
    t
      .uuid('owner_user_id')
      .references('user_id')
      .inTable('user')
  })
}

错误:

migration failed with error: alter table "user" add constraint "user_company_uuid_foreign" foreign key ("company_uuid") references "company" ("company_id") - relation "company" does not exist

我会说它会尝试创建一个 table 并在创建第二个 table(FK 引用)之前添加外键。

关于如何解决这个问题的任何想法。

  1. 这不是真正的 m:n 关系。一个公司可以而且应该只有一个所有者。一个用户必须属于一个公司,否则它不可能存在。如果这无法解决,我可以将 user.company_id 字段作为一个简单的字符串 w/o 任何关系。
  2. 为 user_companies 使用不同的 table 就太过分了。

谢谢!

您是正确的,它试图在它所引用的 table 存在之前创建引用。最简单的方法可能是简单地延迟外键的创建,直到创建 companies table 之后。即

exports.up = async function(knex) {
  await knex.schema.createTable('user', t => {
      t.uuid('user_id').primary()
      t.string('name', 100).notNullable()
      t.string('surname', 100)
      t.string('email').notNullable().unique()
      t.string('password')
      t.boolean('email_confirmed')
        .notNullable()
        .defaultTo(false)
      t.datetime('last_login', { precision: 6 })
        .defaultTo(knex.fn.now(6))
      t.string('language')
      t.string('newsletter')
      t.timestamps(true, true)
      t.uuid('company_id')
  });

  await knex.schema.createTable('company', t => {
    t.uuid('company_id').primary()
    t.string('address_id')
    t.string('name', 100).notNullable()
    t.string('phone')
    t.timestamps(true, true)
    t.uuid('owner_user_id')
      .references('user_id')
      .inTable('user')
  });

  await knex.schema.table('user', t => {
      t.foreign('company_id')
        .references('company_id')
        .inTable('company')
  });
}