【问题标题】:sequelize - Cannot add foreign key constraintsequelize - 无法添加外键约束
【发布时间】:2018-02-13 12:08:12
【问题描述】:

我正在尝试在两个表之间设置 1:1 的关系。 RefreshToken 表将有两个与 Users 表相关的 foreignKey,如下图所示:

我使用 sequelize-auto 来生成我的续集模型。

用户模型:

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('Users', {
    idUsers: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true
    },
    name: {
      type: DataTypes.STRING(45),
      allowNull: true
    },
    mail: {
      type: DataTypes.STRING(45),
      allowNull: false,
      primaryKey: true
    }
  }, {
    tableName: 'Users'
  });
};

RefreshToken 模型:

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('RefreshToken', {
    idRefreshToken: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true
    },
    token: {
      type: DataTypes.TEXT,
      allowNull: true
    },
    userId: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      references: {
        model: 'Users',
        key: 'idUsers'
      }
    },
    userEmail: {
      type: DataTypes.STRING(45),
      allowNull: false,
      primaryKey: true,
      references: {
        model: 'Users',
        key: 'mail'
      }
    }
  }, {
    tableName: 'RefreshToken'
  });
};

当我运行应用程序时,我收到此错误:

未处理的拒绝错误:SequelizeDatabaseError: ER_CANNOT_ADD_FOREIGN:无法添加外键约束

我尝试添加明确的关系,在用户表中添加:

User.associate = (models) => {
    User.hasOne(models.RefreshToken, {
      foreignKey: 'userId'
    });
    User.hasOne(models.RefreshToken, {
      foreignKey: 'userEmail'
    });
  };

在 RefreshToken 中:

RefreshToken.associate = (models) => {
    RefreshToken.belongsTo(models.Users, {
      foreignKey: 'userId'
    });
    RefreshToken.belongsTo(models.Users, {
      foreignKey: 'userEmail'
    });
  };

但我再次收到同样的错误。如果我删除 RefreshToken 表中的引用,我看不到任何错误,但是当我检查数据库时,我看不到任何带有电子邮件和用户 ID 的外键关系约束

【问题讨论】:

标签: javascript mysql node.js express sequelize.js


【解决方案1】:

这是常见的类型错误,主要是因为

1。当主键数据类型和外键数据类型不匹配时

return sequelize.define('RefreshToken', {
    userId: {
      type: DataTypes.INTEGER(11), // The data type defined here and 
      references: {
        model: 'Users',
        key: 'idUsers'
      }
    }, 


return sequelize.define('Users', {
    idUsers: {
      type: DataTypes.INTEGER(11),  // This data type should be the same
    },

2。当引用的键不是主键或唯一键时。

你不能有两个主键,所以其他引用的键应该被定义为唯一的。 unique:true

 return sequelize.define('Users', {
    idUsers: {
      primaryKey: true  
    },
    mail: {
      type: DataTypes.STRING(45),
      allowNull: false,
      primaryKey: true   // You should change this to 'unique:true'. you cant hv two primary keys in one table. 
    }

【讨论】:

  • 看准了!谢谢!!
  • 在我的情况下,我不知道为什么,在我的数据库中我的引用是错误的,引用是另一个不正确的表,我更正了引用并解决了我的问题。
  • 我的情况与@LudOsorio 的情况几乎相同。我没有引用“客户”,而是引用了“客户”。
【解决方案2】:

我看到两个问题:

任何表都不应包含两个主键,并且 userId 不应为整数,而应为 UUID。

我有一个外键设置为 INT,它给了我错误:

未处理的拒绝 SequelizeDatabaseError: 外键约束 “constraint_name_here”无法实现

尝试更改:

userId: {
  type: DataTypes.INTEGER(11),
  allowNull: false,
  primaryKey: true,
  references: {
    model: 'Users',
    key: 'idUsers'
  }
},

收件人

userId: {
  type: DataTypes.UUID,
  allowNull: false,
  foreignKey: true,
  references: {
    model: 'Users',
    key: 'idUsers'
  }
},

【讨论】:

  • 我有一个有两个主键的表。这是一个连接表,两列应该作为一个联合键。似乎工作得很好。
  • 嘿汤姆,你说的完全正确。这两个主键确实是主键,但与连接表无关。从连接表的角度来看,这两个键是指向不同表中主键的外键。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 2020-09-26
  • 1970-01-01
  • 2016-09-28
  • 2020-09-12
相关资源
最近更新 更多