SequelizeDatabaseError:无法截断外键约束中引用的表

Posted

技术标签:

【中文标题】SequelizeDatabaseError:无法截断外键约束中引用的表【英文标题】:SequelizeDatabaseError: Cannot truncate a table referenced in a foreign key constraint 【发布时间】:2019-11-30 16:38:32 【问题描述】:

我正在使用"sequelize": "^5.8.6",我定义了两个模型,companydividend

我的company.js 模型如下所示:

'use strict';
module.exports = (sequelize, DataTypes) => 
  const Company = sequelize.define('Company', 
    company_name: DataTypes.STRING,
    company_link: DataTypes.STRING,
    ticker: DataTypes.STRING,
    description: DataTypes.STRING
  , );
  Company.associate = function(models) 
    Company.hasMany(models.Rating,  onDelete: 'cascade' );
    Company.hasMany(models.Dividend,  onDelete: 'cascade' );
  ;
  return Company;
;

我的dividend.js 模型如下所示:

'use strict';
module.exports = (sequelize, DataTypes) => 
  const Dividend = sequelize.define('Dividend', 
    period: DataTypes.STRING,
    amount: DataTypes.FLOAT,
    payable_date: DataTypes.DATE,
  , );
  Dividend.associate = function(models) 
    Dividend.belongsTo(models.Company,  onDelete: 'cascade' );
  ;
  return Dividend;
;

我的truncate.js 函数如下所示:

const models = require('../models');

const truncateTable = (modelName) =>
  models[modelName].destroy(
    where: ,
    force: true,
  );

module.exports = async function truncate(model) 
  if (model) 
    return truncateTable(model);
  

  return Promise.all(
    Object.keys(models).map((key) => 
      if (['sequelize', 'Sequelize'].includes(key)) return null;
      return truncateTable(key);
    )
  );

当尝试截断两个模型时,我收到以下错误:

 SequelizeDatabaseError: Cannot truncate a table referenced in a foreign key constraint (`test-db`.`dividends`, CONSTRAINT
`dividends_ibfk_1` FOREIGN KEY (`CompanyId`) REFERENCES `test-db`.`companies` (`id`))
    at Query.formatError (c:\test\node_modules\sequelize\lib\dialects\mysql\query.js:239:16)
    at Query.handler [as onResult] (c:\test\node_modules\sequelize\lib\dialects\mysql\query.js:46:23)
    at Query.execute (c:\test\node_modules\mysql2\lib\commands\command.js:30:14)
    at Connection.handlePacket (c:\test\node_modules\mysql2\lib\connection.js:449:32)
    at PacketParser.Connection.packetParser.p [as onPacket] (c:\test\node_modules\mysql2\lib\connection.js:72:12)
    at PacketParser.executeStart (c:\test\node_modules\mysql2\lib\packet_parser.js:75:16)
    at Socket.Connection.stream.on.data (c:\test\node_modules\mysql2\lib\connection.js:79:25)
    at Socket.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at Socket.Readable.push (_stream_readable.js:220:10)
    at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
  name: 'SequelizeDatabaseError',
  parent:
    Error: Cannot truncate a table referenced in a foreign key constraint (`test-db`.`dividends`, CONSTRAINT `dividends_ibfk_1` FOREIGN KEY (`CompanyId`) REFERENCES `test-db`.`companies` (`id`))
       at Packet.asError (c:\test\node_modules\mysql2\lib\packets\packet.js:684:17)
       at Query.execute (c:\test\node_modules\mysql2\lib\commands\command.js:28:26)
       at Connection.handlePacket (c:\test\node_modules\mysql2\lib\connection.js:449:32)
       at PacketParser.Connection.packetParser.p [as onPacket] (c:\test\node_modules\mysql2\lib\connection.js:72:12)
       at PacketParser.executeStart (c:\test\node_modules\mysql2\lib\packet_parser.js:75:16)
       at Socket.Connection.stream.on.data (c:\test\node_modules\mysql2\lib\connection.js:79:25)
       at Socket.emit (events.js:189:13)
       at addChunk (_stream_readable.js:284:12)
       at readableAddChunk (_stream_readable.js:265:11)
       at Socket.Readable.push (_stream_readable.js:220:10)
       at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
     code: 'ER_TRUNCATE_ILLEGAL_FK',
     errno: 1701,
     sqlState: '42000',
     sqlMessage:
      'Cannot truncate a table referenced in a foreign key constraint (`test-db`.`dividends`, CONSTRAINT `dividends_ibfk_1`
FOREIGN KEY (`CompanyId`) REFERENCES `test-db`.`companies` (`id`))',
     sql: 'TRUNCATE `Companies`' ,
  original:
    Error: Cannot truncate a table referenced in a foreign key constraint (`test-db`.`dividends`, CONSTRAINT `dividends_ibfk_1` FOREIGN KEY (`CompanyId`) REFERENCES `test-db`.`companies` (`id`))
       at Packet.asError (c:\test\node_modules\mysql2\lib\packets\packet.js:684:17)
       at Query.execute (c:\test\node_modules\mysql2\lib\commands\command.js:28:26)
       at Connection.handlePacket (c:\test\node_modules\mysql2\lib\connection.js:449:32)
       at PacketParser.Connection.packetParser.p [as onPacket] (c:\test\node_modules\mysql2\lib\connection.js:72:12)
       at PacketParser.executeStart (c:\test\node_modules\mysql2\lib\packet_parser.js:75:16)
       at Socket.Connection.stream.on.data (c:\test\node_modules\mysql2\lib\connection.js:79:25)
       at Socket.emit (events.js:189:13)
       at addChunk (_stream_readable.js:284:12)
       at readableAddChunk (_stream_readable.js:265:11)
       at Socket.Readable.push (_stream_readable.js:220:10)
       at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
     code: 'ER_TRUNCATE_ILLEGAL_FK',
     errno: 1701,
     sqlState: '42000',
     sqlMessage:
      'Cannot truncate a table referenced in a foreign key constraint (`test-db`.`dividends`, CONSTRAINT `dividends_ibfk_1`
FOREIGN KEY (`CompanyId`) REFERENCES `test-db`.`companies` (`id`))',
     sql: 'TRUNCATE `Companies`' ,
  sql: 'TRUNCATE `Companies`' 

有什么建议为什么我会收到此错误?

感谢您的回复!

【问题讨论】:

【参考方案1】:

我认为这与 Sequelize 无关,而是与数据库有关。

How to truncate a foreign key constrained table? 显示了一些处理此限制的选项,这可能适用于Sequelize transaction

【讨论】:

【参考方案2】:

给你:

sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, raw: true )

当您需要重新创建表并以任何父子顺序加载数据时,临时禁用引用约束(将 FOREIGN_KEY_CHECKS 设置为 0)很有用。 SET FOREIGN_KEY_CHECKS = 0

代码:

const models = require('../models');

const truncateTable = (modelName) =>
    models[modelName].destroy(
        where: ,
        force: true,
    );

module.exports = async function truncate(model) 
    if (model) 
        return truncateTable(model);
    
    await sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null,  raw: true ); //<---- Do not check referential constraints
    return Promise.all(
        Object.keys(models).map((key) => 
            if (['sequelize', 'Sequelize'].includes(key)) return null;
            return truncateTable(key);
        )
    );


// once you get the response from truncate, run this, and it will set foreign key checks again
sequelize.query('SET FOREIGN_KEY_CHECKS = 1',  raw: true ); // <-- Specify to check referential constraints

流程:

首先: 使用 SET FOREIGN_KEY_CHECKS = 0 -- 不检查引用约束 第二:这样我们就可以销毁所有的表,并且我们不会得到关于外键约束的错误 第三:一旦所有表都被截断,我们将设置 SET FOREIGN_KEY_CHECKS = 1 -- 指定检查参考 约束

【讨论】:

【参考方案3】:

我知道它很晚才安静,但希望它可以帮助某人。 我正在使用 sequelize 3.35.1,这为我解决了这个问题:

    sequelize = new Sequelize("database_name", "Username", "password");

    sequelize.query('SET GLOBAL FOREIGN_KEY_CHECKS = 0;',  raw: true );
    // Do Some Action
    sequelize.query('SET GLOBAL FOREIGN_KEY_CHECKS = 1;',  raw: true );

仅 SET GLOBAL FOREIGN_KEY_CHECKS = 0;没有为我做这个把戏。

【讨论】:

以上是关于SequelizeDatabaseError:无法截断外键约束中引用的表的主要内容,如果未能解决你的问题,请参考以下文章

SequelizeDatabaseError:关系“设备”不存在

获取 DatabaseError [SequelizeDatabaseError],不正确的整数值

SequelizeDatabaseError:运算符不存在:字符变化 [] @> 字符变化

收到以下错误:“SequelizeDatabaseError 列“createdAt”不存在”

未处理的拒绝 SequelizeDatabaseError: 未选择数据库

Postgres SequelizeDatabaseError:返回或接近返回的语法错误