【问题标题】:Issue with Knex migrationKnex 迁移问题
【发布时间】:2019-08-12 03:39:02
【问题描述】:

我不确定似乎是什么问题,但是这个 knex 迁移失败了。即使我是编写迁移的新手,我也坚信这个迁移文件是正确的。产生的错误如下

migration file "20190321113401_initial.js" failed
migration failed with error: alter table "meraki"."role_permissions" add constraint "role_permissions_role_id_foreign" foreign key ("role_id") references "roles" ("id") - relation "roles" does not exist

代码如下。最初,这些迁移功能位于单独的文件中,我认为它失败了,因为文件没有同步执行,这导致我编写了一个文件。我不确定这是否有帮助,但是当我删除包含外键引用(UserRoles、RolePermissions、Tokens)的表的代码时,其余部分似乎正在工作。

'use strict';

exports.up = async knex => {
  // Create Schema
  await knex.raw('CREATE SCHEMA IF NOT EXISTS meraki');
  // Load Extensions
  await knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');
  // Roles
  await knex.schema.withSchema('meraki').createTable('roles', table => {
    table
      .string('id')
      .primary()
      .defaultTo(knex.raw('uuid_generate_v4()'));
    table
      .string('name')
      .unique()
      .notNullable();
    table.string('description').notNullable();
    table.timestamps();
  });
  // Permissions
  await knex.schema.withSchema('meraki').createTable('permissions', table => {
    table
      .string('id')
      .primary()
      .defaultTo(knex.raw('uuid_generate_v4()'));
    table
      .string('name')
      .unique()
      .notNullable();
    table.timestamps();
  });
  // Role Permissions
  await knex.schema.withSchema('meraki').createTable('role_permissions', table => {
    table
      .string('role_id')
      .notNullable()
      .references('id')
      .inTable('roles');
    table
      .string('permission_id')
      .notNullable()
      .references('id')
      .inTable('permissions');
    table.timestamps();
  });
  // Users
  await knex.schema.withSchema('meraki').createTable('users', table => {
    table
      .string('id')
      .primary()
      .defaultTo(knex.raw('uuid_generate_v4()'));
    table
      .string('email', 320)
      .unique()
      .notNullable();
    table.string('first_name', 35).notNullable();
    table.string('middle_name', 35).notNullable();
    table.string('last_name', 35).notNullable();
    table.boolean('email_verified');
    table.string('verification_token');
    table.timestamps();
  });
  // User Roles
  await knex.schema.withSchema('meraki').createTable('user_roles', table => {
    table
      .string('user_id')
      .notNullable()
      .references('id')
      .inTable('users');
    table
      .string('role_id')
      .notNullable()
      .references('id')
      .inTable('roles');
    table.timestamps();
  });
  // Tokens
  await knex.schema.withSchema('meraki').createTable('tokens', table => {
    table.string('id').primary();
    table
      .string('user_id')
      .notNullable()
      .references('id')
      .inTable('users');
    table
      .bigInteger('ttl')
      .notNullable()
      .defaultTo(1209600);
    table.timestamps();
  });
};

exports.down = async knex => {
  // Tokens
  await knex.schema.withSchema('meraki').dropTableIfExists('tokens');
  // User Roles
  await knex.schema.withSchema('meraki').dropTableIfExists('user_roles');
  // Users
  await knex.schema.withSchema('meraki').dropTableIfExists('users');
  // Role Permissions
  await knex.schema.withSchema('meraki').dropTableIfExists('role_permissions');
  // Permissions
  await knex.schema.withSchema('meraki').dropTableIfExists('permissions');
  // Roles
  await knex.schema.withSchema('meraki').dropTableIfExists('roles');
  // Drop Extensions
  await knex.raw('DROP EXTENSION IF EXISTS "uuid-ossp"');
  // Delete Schema
  await knex.raw('DROP SCHEMA IF EXISTS meraki');
};

【问题讨论】:

  • 你使用的是哪个版本的 postgresql?
  • 我使用的是 postgres 10.5。您认为这里存在兼容性问题吗?
  • 我认为问题在于 PG 需要使用两个列名自动生成约束的名称,但是您在 create 中发出一条语句并且 FK 的列名不可用(在create sql knex 正在构建)以正确命名约束。您可以尝试在等待创建的下方使用 alter table 命令添加外键吗?所以问题不是来自knex,而是来自PG。如果可行,我会将其发布为答案
  • 但是为什么不可用呢?我正在串行执行这些命令,并且该列应该可供参考,对吗?我会试试你的建议。但是您没有发现我的代码有任何问题吗?
  • 查看例如thisthis 如何使用名称或在两个单独的语句中添加约束(虽然逗号作为语法糖,但可能作为事务运行)

标签: node.js postgresql knex.js


【解决方案1】:

做这样的事情-

await knex.schema.withSchema('meraki').createTable('role_permissions', table => {
    table
      .string('role_id')
      .notNullable()
      .references('id')
      .inTable('meraki.roles'); // scmema attached.
    table
      .string('permission_id')
      .notNullable()
      .references('id')
      .inTable('meraki.permissions');  // scmema attached.
    table.timestamps();
  })

【讨论】:

  • 非常感谢,你是一个救生员。它奏效了,非常抱歉迟到的回复。但是如果不明确指定架构名称,它不应该工作吗?
  • 只要通过调用toString()来生成SQL,你就会知道为什么它现在可以在没有模式部分的情况下工作了。
猜你喜欢
  • 1970-01-01
  • 2017-03-18
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
  • 2020-01-17
相关资源
最近更新 更多