PostgreSQL表的入口违反了外键约束

时间:2016-09-18 11:24:43

标签: javascript postgresql foreign-keys relational-database sequelize.js

我正在使用sequelize来定义我的表及其关系,然后在表格中插入一些条目。

我有三张桌子:

  • BankAccounts :pk - accountNumber
  • 商家:pk - 序列ID
  • BusinessBankAccounts :pk-bankAccountAccountNumber& businessId

关系:

BankAccount.belongsToMany(Business, {through: 'BusinessBankAccounts'});

为BankAccount和Business创建条目:

Connection.models.bankAccount.create({accountNumber: 12345678, ...});
Connection.models.business.create({...});

这两个条目正确地插入到表中(使用pgAdmin来检查我的数据库),但是只要我试图插入一个条目来连接这两个:

Connection.models.BusinessBankAccounts.create({bankAccountAccountNumber: 12345678,
                                               businessId: 1});

弹出错误:

Unhandled rejection SequelizeForeignKeyConstraintError: insert or update on table 
"BusinessBankAccounts" violates foreign key constraint
"BusinessBankAccounts_bankAccountAccountNumber_fkey"

注意:使用pgAdmin工具手动插入完全相同的条目不会弹出错误,并且已插入!

非常感谢任何帮助!

提前致谢。

2 个答案:

答案 0 :(得分:2)

感谢@wildplasser评论,我在sequelize transaction docs上找到了如何强制提交一些插入内容。

结束如下:

Connection.transaction((t)=> {
     return Promise.all([
       Connection.models.bankAccount.create({accountNumber: 12345678, ...}, 
                                            {transaction: t}),
       Connection.models.business.create({...},
                                         {transaction: t})
     ]).then((result)=> {
         Connection.models.BusinessBankAccounts.create({
             bankAccountAccountNumber: 12345678,
             businessId: 1
         });
     })
}

答案 1 :(得分:1)

我在使用Sequelize和Postgres时遇到了同样的问题。

经过一些研究,我发现了“可延迟的”。 Postgres的功能似乎是我的问题的解决方案。

你有什么工作,Kesem。我的解决方案为Sequelize的事务添加了一个选项,以启用Postgres的可延迟功能,允许我插入尽可能多的行并推迟外键约束检查,直到事务即将提交而不是Postgres检查每个insert语句后立即生成约束。这允许我一次运行所有我的create语句,而不是像你一样创建一个Promise链。

var objectsToCreate = []
// all 3 of the objects you want to insert. 
objectsToCreate.push({accountNumber: 12345678, ...}) 
objectsToCreate.push({...})
objectsToCreate.push({bankAccountAccountNumber: 12345678, businessId: 1})

await sequelize.transaction({
  deferrable: sequelize.Deferrable.SET_DEFERRED // magic sauce.
}, (transaction) => {
  var promises = []
  objectsToCreate.forEach((objectToCreate) => {
    promises.push(Connection.models.BusinessBankAccounts.create(objectToCreate, {transaction:transaction}))
  })
  // Here, we are able to run all the queries at one time. No having to deal with a Promise().then().then().then() chain. 
  return Promise.all(promises)
})