web-dev-qa-db-ja.com

sequelize-外部キー制約を追加できません

2つのテーブル間に1:1の関係を設定しようとしています。この画像のように、RefreshTokenテーブルには、Usersテーブルに関連付けられた2つのforeignKeyがあります: enter image description here

Sequelize-autoを使用して、sequelizeモデルを生成しました。

ユーザーモデル:

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:外部キー制約を追加できません

関係を明示的に追加して、Usersテーブルに追加しようとしました。

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を含む外部キー関係の制約が表示されません。

10
tinytanks

これは一般的なタイプのエラーで、主に

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.参照されるキーが主キーまたは一意のキーではない場合。

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. 
    }
14

2つの問題が表示されます。

テーブルに2つの主キーを含めないでください。userIdを整数にすることはできません。UUIDにする必要があります。

外部キーをINTに設定すると、エラーが発生しました。

未処理の拒否SequelizeDatabaseError:外部キー制約「constraint_name_here」を実装できません

変更してみてください:

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

To

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