[英]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.