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 主键来解决这个问题。
同时关注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 主键来解决这个问题。