简体   繁体   English

Node.js中的SERIAL违反外键

[英]Foreign key violations with SERIAL in Node.js

While following the cockroachdb example for building an app using the sequelize orm for node.js, I expanded upon it to add associations between my models. 在遵循关于使用node.js的续集 orm构建应用程序的cockroachdb示例时 ,我对其进行了扩展以在模型之间添加关联。 Primary keys are INT with auto-increment via unique_rowid(). 主键是通过unique_rowid()自动递增的INT。 Based on your documentation, this is your implementation of SERIAL . 根据您的文档,这是SERIAL的实现。

After synching my models, I attempt to create records using the following code: 同步模型后,我尝试使用以下代码创建记录:

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 }
    ])
  })

When this is run, I get " error: foreign key violation: value [255737842446434300] not found in customers@primary [id] " 运行此命令时,出现“ error: foreign key violation: value [255737842446434300] not found in customers@primary [id]

I realize my parseInt doesn't appear to have the precision required in order to take the string id returned from the customer creation, but I don't know how to accomplish this. 我意识到我的parseInt似乎不具备从客户创建中返回的字符串ID所需的精度,但是我不知道该如何完成。

Update, 6 July 2017. 更新,2017年7月6日。

The latest version of sequelize-cockroachdb , v1.0.2, teaches Sequelize to coerce strings used in numeric contexts into CockroachDB integers. sequelize-cockroachdb的最新版本v1.0.2教导Sequelize将数字上下文中使用的字符串强制转换为CockroachDB整数。 Simply don't call parseInt on result.dataValues.id and it should work as you expect! 只需不对result.dataValues.id调用parseInt result.dataValues.id ,它应该可以按预期工作!

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 }
    ])
  })

The problem, as you've discovered, is that IDs generated by unique_rowid() , like 255737842446434300, are too large to fit in a JavaScript Number , which can only exactly represent integers up to 2 53 - 1. The usual solution to this problem is to use strings instead. 这个问题,因为你已经发现,是一种通过生成的ID unique_rowid()像255737842446434300,太大而不能在JavaScript的号码 ,它只能完全代表整数多达2 53 - 1。通常解决这个问题是使用字符串代替。 That is, you could simply elide the call to parseInt and pass { ..., customer_id: "255737842446434300"} directly to Order.bulkCreate . 也就是说,您可以简单地取消对parseInt的调用,并将{ ..., customer_id: "255737842446434300"}直接传递给Order.bulkCreate

Unfortunately, Sequelize will then generate a SQL statement that looks like this: 不幸的是,Sequelize随后将生成如下所示的SQL语句:

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

PostgreSQL will happily convert that string literal into an int8 , but CockroachDB will complain about using a string literal where an int8 is expected. PostgreSQL会很乐意将该字符串文字转换为int8 ,但是CockroachDB会抱怨在期望int8地方使用字符串文字。 I have open PRs to fix this on either the CockroachDB side or the Sequelize adapter side , but neither has landed yet. 我有开放的PR可以在CockroachDB端Sequelize适配器端解决此问题,但是都没有登陆。 We'll almost certainly have a solution for v1.1, however! 我们几乎肯定会为v1.1提供解决方案!


In the meantime—particularly if you want a solution compatible with CockroachDB v1.0—you can work around the issue by using UUID primary keys with the Sequelize.BLOB type. 同时,特别是如果您想与CockroachDB v1.0兼容的解决方案,您可以通过使用Sequelize.BLOB类型的UUID主键来解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM