sequelize: cascade delete does not work

i associated lines with orders like following but I want to delete them as relational but it didn’t work, what could be reason for this ?

 associate: function(models) {
      Orders.hasMany(models.lines, { onDelete: 'cascade' });
    }

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 23 (2 by maintainers)

Commits related to this issue

Most upvoted comments

I had the same issue. I was missing hooks: true,. Adding it solved the issue. Recommend trying the below:

Orders.hasMany(models.lines, { 
  onDelete: 'cascade',
  hooks: true, 
});

I was able to find some insight here: http://docs.sequelizejs.com/manual/tutorial/hooks.html#associations

Ofcourse its still an issue…

The problem is missing CONSTRAINT in schema. So, the solution is add a migration script to add foreign key field into table:

Here’s my answer on SO: Sequelize.js onDelete: ‘cascade’ is not deleting records sequelize

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn(
      'Product', // name of Source model
      'categoryId', // name of the key we're adding 
      {
        type: Sequelize.INTEGER,
        references: {
          model: 'Category', // name of Target model
          key: 'id', // key in Target model that we're referencing
        },
        onUpdate: 'CASCADE',
        onDelete: 'CASCADE',
      }
    );
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn(
      'Product', // name of Source model
      'categoryId' // key we want to remove
    );
  }
};

Hope this help!

Same issue. Solved by changing this

const user = await User.destroy({
    where: {
      id: '1394',
    },
 });

to

const user = await User.findOne({
   where: {
     id: '1394',
   },
});
await user.destroy();

No sure how this is solving is

This bug still exists

Two points to note:

  1. Has Many relationship should come before the BelongsTo
  2. BelongsTo should also contain the foreign Key option with same key as in hasMany
Donor.hasMany(Donation, {
  foreignKey: "donorId",
  onDelete: "cascade",
});
Donation.belongsTo(Donor, { foreignKey: "donorId" });

This worked for me

I had the same issue, fixed it with changing the order of associations declaration. The hasMany needs to be declared before the belongsTo.

User.hasMany(Book, { onDelete: 'CASCADE', hooks: true });
Book.belongsTo(User);

Same issue. Solved by changing this

const user = await User.destroy({
    where: {
      id: '1394',
    },
 });

to

const user = await User.findOne({
   where: {
     id: '1394',
   },
});
await user.destroy();

No sure how this is solving is

This problem is old but still today this is what solved it for me. If anyone knows a simpler way let me know.

I had the same issue, fixed it with changing the order of associations declaration. The hasMany needs to be declared before the belongsTo.

User.hasMany(Book, { onDelete: 'CASCADE', hooks: true });
Book.belongsTo(User);

this solves my issue. thanks

Banging my head on the same issue. Basically I have items and outfits. I want to have many items that can possibly belong to many outfits. When I delete an item, I want to also delete every associated outfit. Ended up like this:

const { Sequelize, Model, DataTypes } = require('sequelize');

const sequelize = new Sequelize('sqlite::memory:');

const Item = sequelize.define('Item', {
    name: DataTypes.STRING,
});

const Outfit = sequelize.define('Outfit', {
    name: DataTypes.STRING,
});

Item.belongsToMany(Outfit, {through:'Item-Outfit', onDelete:'CASCADE', hooks:true});
Outfit.belongsToMany(Item, {through:'Item-Outfit'});


(async ()=>{
    await sequelize.sync();
    // Create some items.
    let shoes = await Item.create({name:"shoes"});
    let pants = await Item.create({name:"pants"});

    // Create an outfit.
    let outfit = await Outfit.create({name:"mynewoutfit"});

    // Add items to outfit.
    await outfit.addItem(shoes, {through:'Item-Outfit'});
    await outfit.addItem(pants, {through:'Item-Outfit'});

    // Print outfit.
    let result = await Outfit.findOne({where:{name:'mynewoutfit'}});
    console.log(result); 

    // Destroy one item included in outfit.
    let shoe = await Item.findOne({where:{name:"shoes"}});
    await shoe.destroy();

    // Lookup outfit (should return null).
    result = await Outfit.findOne({where:{name:'mynewoutfit'}});
    console.log(result);
})();

Look-up then destroy + the hooks:true did the trick. It’s not optimal, I don’t like 2 calls for one deletion but I think it does work.

@lumpov it’s not the same bug. Your tables are paranoid. Deleting something from a paranoid table updates its deleted_at column. It’s not a delete statement so the ON DELETE clause doesn’t apply

This is the issue you’re looking for: https://github.com/sequelize/sequelize/issues/2586


We’ll double check before closing but I’m pretty sure this issue is resolved in Sequelize 7

Same issue. Solved by changing this

const user = await User.destroy({
    where: {
      id: '1394',
    },
 });

to

const user = await User.findOne({
   where: {
     id: '1394',
   },
});
await user.destroy();

No sure how this is solving is

Not sure how does it solving, but it works. Thanks!

The problem is missing CONSTRAINT in schema. So, the solution is add a migration script to add foreign key field into table:

Here’s my answer on SO: Sequelize.js onDelete: ‘cascade’ is not deleting records sequelize

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn(
      'Product', // name of Source model
      'categoryId', // name of the key we're adding 
      {
        type: Sequelize.INTEGER,
        references: {
          model: 'Category', // name of Target model
          key: 'id', // key in Target model that we're referencing
        },
        onUpdate: 'CASCADE',
        onDelete: 'CASCADE',
      }
    );
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn(
      'Product', // name of Source model
      'categoryId' // key we want to remove
    );
  }
};

Hope this help!

This helped me!