Nodejs sequelize 如何截断外键引用的表
Posted
技术标签:
【中文标题】Nodejs sequelize 如何截断外键引用的表【英文标题】:Nodejs sequelize how to truncate a foreign key referenced table 【发布时间】:2014-05-21 05:28:40 【问题描述】:[重要:这仅与 Sequelize Version
我有一个“myTable”mysql 表,其中 myTable.id 由另一个表上的外键引用。我需要截断“myTable”。通常使用 mysql shell 我会这样做:
mysql> SET FOREIGN_KEY_CHECKS = 0; truncate table myTable; SET FOREIGN_KEY_CHECKS = 1;
sequelize 有没有办法做到这一点?
我已尝试执行
sequelize.query('SET FOREIGN_KEY_CHECKS = 0; truncate table myTable; SET FOREIGN_KEY_CHECKS = 1;')
但我有错误:
`Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'truncate table myTable; SET FOREIGN_KEY_CHECKS = 1' at line 1`
如果我连续执行查询,我无法截断表格:
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint
【问题讨论】:
【参考方案1】:这种情况正在发生,因为 sequelize 不允许您通过单个 sequelize.query
调用执行多个查询。现在只为sequelize.sync( force: true )
处理所描述的场景,它会删除所有表并在之后重新创建它们。该方法在内部使用以下代码:
https://github.com/sequelize/sequelize/blob/a014bd8d172fb8fd9881cee866abfcab842c30fc/lib/query-interface.js#L227-228
它基本上加载每个表并检查是否有外键。如果是这种情况,sequelize 会将它们放在另一个表之前。你可能会采用这个逻辑。此外:如果你决定实现这些东西,你可能会在 github 上打开一个拉取请求。那会很艰难。另一个可能可行的选项如下:
sequelize.transaction(function(t)
var options = raw: true, transaction: t
sequelize
.query('SET FOREIGN_KEY_CHECKS = 0', null, options)
.then(function()
return sequelize.query('truncate table myTable', null, options)
)
.then(function()
return sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, options)
)
.then(function()
return t.commit()
)
).success(function()
// go on here ...
)
之所以有效,是因为事务使用专用连接,这意味着您可以轻松地连续执行命令。
【讨论】:
所以,换句话说,我们必须自己关心我们的 FK,因为 Sequelize 总是在这方面失败github.com/sequelize/sequelize/issues/6894 我有一个错误:Error: Sequelize.query was refactored to only use the parameters 'sql' and 'options'. Please read the changelog about BC.
注意:对于 V5 及以上用户,options
参数现在应该是第二个参数,如下所示:sequelize.query('your query here', options)【参考方案2】:
我正在使用 sequelise 版本 3.5.1 和 sdepolds solution 不再工作,因为 sequelise api 已更改。调整他的解决方案将导致:
sequelize.transaction(function(t)
var options = raw: true, transaction: t
return sequelize
.query('SET FOREIGN_KEY_CHECKS = 0', options)
.then(function()
return sequelize.query('truncate table myTable', options)
)
.then(function()
return sequelize.query('SET FOREIGN_KEY_CHECKS = 1', options)
)
).then(function()
// go on here ...
)
根据Sequelise's documentation 链中的最后一个promise 触发事务的提交。 sdepolds 答案中的第二个参数(null)也不再需要了。此外,必须为 outta 返回 sequelize.query。
【讨论】:
我有一个错误:Error: Sequelize.query was refactored to only use the parameters 'sql' and 'options'. Please read the changelog about BC.
【参考方案3】:
我正在使用 sequelize 3.24.3,你可以这样做
MyTableModel.truncate( cascade: true );
这里是cascade
选项的文档
仅与 TRUNCATE 一起使用。截断所有对命名表有外键引用的表,或者截断由于 CASCADE 而添加到组中的任何表。
【讨论】:
不起作用。SequelizeDatabaseError: ER_TRUNCATE_ILLEGAL_FK: Cannot truncate a table referenced in a foreign key constraint
您使用的是兼容版本吗?
使用sequelize
:3.24.3
,FK 约束配置为ON DELETE SET NULL
。【参考方案4】:
我通过查看 another question 得到了这个,它在 v4.13.2 上对我有用
MyTableModel.destroy( truncate: cascade: true );
【讨论】:
【参考方案5】:如果您使用过 Sequelize 5,并且您已经在模型中定义了关联并将“onDelete”属性设置为“CASCADE”,则无需添加“truncate”或“cascade”属性到“销毁”方法参数。 而是这样做:
MyTableModel.destroy( where: );
表格将被截断。
【讨论】:
【参考方案6】:在onDelete: CASCADE
的情况下,Sequelize 6.3.5 对我不起作用
作为最后的手段,我设法在单元测试中截断表,如下所示:
await MyModel.sequelize.query("SET FOREIGN_KEY_CHECKS = 0", null);
await MyModel.truncate();
await MyModel.sequelize.query("SET FOREIGN_KEY_CHECKS = 1", null);
【讨论】:
以上是关于Nodejs sequelize 如何截断外键引用的表的主要内容,如果未能解决你的问题,请参考以下文章