Sequelize - 更新 FOREIGN KEY 约束赢得 ONDELETE CASCADE

dan*_*rvt 5 postgresql node.js sequelize.js

我正在将 Postgres 与 Sequelize 一起使用,我需要ForeignKey使用onDelete = Cascade.

我已经更新了我的模型,但迁移文件作为一个骨架出现。我还没有找到更新这个约束的方法。

我的模型文件

export const Property = sequelize.define<PropertyModel, PropertyAttribute>('property', {
  id: {
    type: Sequelize.UUID,
    primaryKey: true,
    defaultValue: Sequelize.UUIDV4,
    allowNull: false
  },
  name: Sequelize.STRING,
  status: {
    type: Sequelize.BOOLEAN,
    defaultValue: true
  },
  publishedAt: Sequelize.DATE
});

Property.associate = models => {
  Property.belongsTo(models.User, {
    foreignKey: { allowNull: false },
    allowNull: false
  });
  Property.hasMany(
    models.PropertyService, {onDelete: "cascade"});

  Property.hasMany(
    models.Visitor, {onDelete: "cascade"});
};
Run Code Online (Sandbox Code Playgroud)

我的迁移文件

module.exports = {
  up: (queryInterface, Sequelize) => {
      // How can I update a FK constraint??
  },

  down: (queryInterface, Sequelize) => {
      // How can I undo an FK update constraint??
  }
};
Run Code Online (Sandbox Code Playgroud)

关于如何进行此迁移的任何想法?

Sto*_*one 6

我发现最简单的方法是首先删除现有约束,然后使用 onDelete 将其添加回来。Sequelize有queryInterface.removeConstraintqueryInterface.addConstraint这个方法。

这是一个人为的例子:

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    const transaction = await queryInterface.sequelize.transaction();
    try {
      await queryInterface.removeConstraint(
        'users',
        'users_address_id_fkey',
        { transaction }
      );
      await queryInterface.addConstraint('users', ['address_id'], {
        type: 'foreign key',
        name: 'users_address_id_fkey',
        references: {
          table: 'addresses',
          field: 'id',
        },
        onDelete: 'CASCADE',
        transaction
      });
      return transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },

  down: async (queryInterface, Sequelize) => {
    const transaction = await queryInterface.sequelize.transaction();
    try {
      await queryInterface.removeConstraint(
        'users',
        'users_address_id_fkey',
        { transaction }
      );
      await queryInterface.addConstraint('users', ['address_id'], {
        type: 'foreign key',
        name: 'users_address_id_fkey',
        references: {
          table: 'addresses',
          field: 'id',
        },
        transaction
      });
      return transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },
};
Run Code Online (Sandbox Code Playgroud)

  • 在你的情况下,“transaction”什么都不做,你需要将其包含到查询中 (2认同)
  • 仅供参考@Stone,对于sequelize v6上的那些,您需要将字段放置在选项对象内,例如`options.fields`,否则它将抛出错误[doc here](https://sequelize.org/master/class /lib/dialects/abstract/query-interface.js~QueryInterface.html#instance-method-addConstraint) (2认同)

Tim*_*hel 3

我不相信有任何方法可以从标准 Sequelize 迁移查询接口中操纵约束,因此我过去实现此目的的方法是ALTER TABLE在 PostgreSQL 上运行原始查询来删除并重新创建约束FOREIGN KEY,例如:

const tableName = 'property';
const constraintName = 'property_property_service_id_fkey';

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.sequelize.query(`alter table "${tableName}" drop constraint "${constraintName}"`)
      .then(() => queryInterface.sequelize.query(
        `alter table "${tableName}"
          add constraint "${constraintName}" foreign key("property_service_id") references "property_service" ("id")
          on delete cascade`
      ));
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.sequelize.query(`alter table "${tableName}" drop constraint "${constraintName}"`)
      .then(() => queryInterface.sequelize.query(
        `alter table "${tableName}"\
          add constraint "${constraintName}" foreign key("property_service_id") references "property_service" ("id")
          on delete no action`
      ));
  },
};
Run Code Online (Sandbox Code Playgroud)

请注意,我对您的表、字段和约束名称做了一些假设,因此您可能需要根据您的 Sequelize 配置设置来调整其中的一些名称。