LoginSignup
4
3

More than 3 years have passed since last update.

sequelize の migrationで外部キー制約を貼り付けた時の undo 時の設定

Last updated at Posted at 2018-07-11

TL;DR

removeConstraint だけではなく removeIndex も指定しよう。

どうして?

constraint を導入した時に同時に index が張られるので、 removeConstraint だけすると index が残ってしまうため。

気になる人は具体例を後ろの方に書いてあるのでそちらを参照。

正解の記述例

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return [
      queryInterface.addConstraint(
        'members',
        ['group_id'],
        {
          type: 'foreign key',
          name: 'members_group_id_groups_fk',
          references: {
            table: 'groups',
            field: 'id',
          },
          onDelete: 'cascade',
        },
      ),
    ];
  },
  down: async (queryInterface, Sequelize) => {
    return [
      await queryInterface.removeConstraint('members', 'members_group_id_groups_fk'),
      await queryInterface.removeIndex('members', 'members_group_id_groups_fk'),
    ];
  }
};

実際にやってみる

スキーマ

例えば以下のような関係のテーブルがあったとする。
group_member.png

up する

それぞれのテーブルは既に create されているものとして、 members.group_id の外部キー制約として groups.id を設定したい場合、 up 時の記述としては以下のようになる。

addConstraint(
  'members',
  ['group_id'],
  {
    type: 'foreign key',
    name: 'members_group_id_groups_fk',
    references: {
      table: 'groups',
      field: 'id',
    },
    onDelete: 'cascade',
  },
)

sequelize db:migrate 実行後に SHOW CREATE TABLE members; を発行すると以下のように、 contraint とさらに index が追加されていることがわかる。

CREATE TABLE `members ` (
  `id` char(26) COLLATE utf8mb4_unicode_ci NOT NULL,
  `group_id` char(26) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `name` char(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  KEY `members_group_id_groups_fk` (`group_id`),
  CONSTRAINT `members_group_id_groups_fk`
  FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

down に removeConstraint だけ記述

removeConstraint('members', 'members_group_id_groups_fk')

だけ記述して sequelize db:migrate:undo を実行し、SHOW CREATE TABLE members; を発行して確認する。

CREATE TABLE `members ` (
  `id` char(26) COLLATE utf8mb4_unicode_ci NOT NULL,
  `group_id` char(26) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `name` char(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  KEY `members_group_id_groups_fk` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

バッチリ index が残っておりますな。

備考

addConstraint の name は省略可

addConstraint で name を書かない場合、自動的に key 名が生成される。
しかしそれだと removeConstraint ができないので、適当なものを記述しておくと良い。
(書かずにやる方法はあるにはあるが、オススメするメリットはない)

await と順番

removeConstraintremoveIndex に await を指定している。
これは制約が解除されてからじゃないと index を剥がせないため。
await にするので、実行元の関数に async を指定するのを忘れずに。

実際にやってしまった人の対応策

残ってしまった index を手動で削除する MySQL 文は以下の通り。
ALTER TABLE [table_name] DROP INDEX [index_name];

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3