Node.js 中的 SERIAL 外键违规

Foreign key violations with SERIAL in Node.js

同时关注cockroachdb example for building an app using the sequelize orm for node.js, I expanded upon it to add associations between my models. Primary keys are INT with auto-increment via unique_rowid(). Based on your documentation, this is your implementation of SERIAL

同步我的模型后,我尝试使用以下代码创建记录:

models.sequelize.sync({ force: true })
  .then(function () {
    return models.Customer.create({
      name: "Sample Customer"
    })
  })
  .then(function (result) {
    const id = parseInt(result.dataValues.id, 10)
    return models.Order.bulkCreate([
      { subtotal: 100.00, customer_id: id },
      { subtotal: 200.00, customer_id: id }
    ])
  })

当这是 运行 时,我得到“error: foreign key violation: value [255737842446434300] not found in customers@primary [id]

我意识到我的 parseInt 似乎没有获取客户创建返回的字符串 ID 所需的精度,但我不知道如何完成此操作。

更新,2017 年 7 月 6 日。

sequelize-cockroachdb 的最新版本 v1.0.2 教导 Sequelize 将数字上下文中使用的字符串强制转换为 CockroachDB 整数。不要在 result.dataValues.id 上调用 parseInt,它应该会如您所愿地工作!

models.sequelize.sync({ force: true })
  .then(function () {
    return models.Customer.create({
      name: "Sample Customer"
    })
  })
  .then(function (result) {
    return models.Order.bulkCreate([
      { subtotal: 100.00, customer_id: result.dataValues.id },
      { subtotal: 200.00, customer_id: result.dataValues.id }
    ])
  })

正如您所发现的,问题是由 unique_rowid() 生成的 ID,例如 255737842446434300,太大而无法放入 JavaScript Number,它只能精确表示最大为 2 的整数53 - 1.这个问题通常的解决方法是 改为使用字符串。也就是说,您可以简单地省略对 parseInt 的调用并将 { ..., customer_id: "255737842446434300"} 直接传递给 Order.bulkCreate.

不幸的是,Sequelize 然后会生成一个 SQL 语句,如下所示:

INSERT INTO orders (customer_id) VALUES ('255737842446434300');

PostgreSQL 会很乐意将该字符串文字转换为 int8,但 CockroachDB 会抱怨在需要 int8 的地方使用字符串文字。我已经打开 PR 来解决 CockroachDB side or the Sequelize adapter side 上的这个问题,但都还没有落地。但是,我们几乎肯定会为 v1.1 提供解决方案!


同时——特别是如果你想要一个与 CockroachDB v1.0 兼容的解决方案——你可以通过使用 Sequelize.BLOB 类型的 UUID 主键来解决这个问题。