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 如何截断外键引用的表的主要内容,如果未能解决你的问题,请参考以下文章

如何在sequelize中将外键引用到另一个外键?

如何截断外键约束表?

如何截断外键约束表?

sequelize 中的引用字段是啥?

如何使用 Sequelize 和 mySql 选择外键列的名称?

同步执行 Sequelize 查询