续集-更新FOREIGN KEY约束赢得ONDELETE CASCADE

时间:2018-08-20 16:25:25

标签: node.js postgresql 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"});
};

我的迁移文件

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

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

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

2 个答案:

答案 0 :(得分:2)

我不认为可以通过标准的Sequelize迁移queryInterface来处理约束,因此我过去实现此目标的方法是在PostgreSQL上运行原始ALTER TABLE查询以删除并重新执行-创建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`
      ));
  },
};

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

答案 1 :(得分:2)

我发现最简单的方法是先删除现有约束,然后使用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;
    }
  },
};