MySQL: "ON DELETE SET NULL" オプションを使って、複数列外部キーを持つテーブルで特定の列のみをNULLに設定する方法
MySQLで複数列外部キーを持つテーブルで、削除時に特定の列のみをNULLに設定する方法
MySQLで、複数の列を持つ外部キーを持つテーブルにおいて、関連する親テーブルのレコードを削除した際に、子テーブルの特定の列のみをNULLに設定する方法について説明します。
問題
通常、外部キー制約を持つ子テーブルのレコードを削除しようとすると、関連する親テーブルのレコードが存在しない場合は、子テーブルのレコードも削除されます。
しかし、場合によっては、子テーブルのレコードを削除せずに、特定の列のみをNULLに設定したい場合があります。
解決策
この問題を解決するには、ON DELETE SET NULL
オプションを使用します。
手順
CREATE TABLE child_table (
id INT NOT NULL AUTO_INCREMENT,
parent_id INT,
other_column VARCHAR(255),
FOREIGN KEY (parent_id) REFERENCES parent_table (id)
ON DELETE SET NULL
);
- 親テーブルのレコードを削除します。
DELETE FROM parent_table WHERE id = 1;
SELECT * FROM child_table;
id | parent_id | other_column
------- | -------- | --------
1 | NULL | This is a value
2 | 2 | This is another value
上記のように、parent_id
列はNULLに設定されますが、other_column
列は保持されます。
注意事項
ON DELETE SET NULL
オプションは、親テーブルと子テーブルの関係が1対多の場合にのみ使用できます。ON DELETE SET NULL
オプションを使用すると、子テーブルのデータ整合性が損なわれる可能性があります。
補足
- 上記の例では、
other_column
列以外にも、複数の列をNULLに設定したい場合は、ON DELETE SET NULL
オプションに複数の列名をカンマ区切りで指定できます。 ON DELETE SET NULL
オプション以外にも、ON DELETE CASCADE
オプションなど、削除時の動作を指定するオプションがあります。
- 外部キー制約に関する詳細は、MySQLリファレンスマニュアルを参照してください。
- データベースの設計や運用に関しては、専門知識を持つエンジニアに相談することをお勧めします。
親テーブル
CREATE TABLE parent_table (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255),
PRIMARY KEY (id)
);
CREATE TABLE child_table (
id INT NOT NULL AUTO_INCREMENT,
parent_id INT,
other_column VARCHAR(255),
FOREIGN KEY (parent_id) REFERENCES parent_table (id)
ON DELETE SET NULL
);
データ挿入
INSERT INTO parent_table (name) VALUES ('Parent 1');
INSERT INTO parent_table (name) VALUES ('Parent 2');
INSERT INTO child_table (parent_id, other_column) VALUES (1, 'This is a value');
INSERT INTO child_table (parent_id, other_column) VALUES (1, 'This is another value');
INSERT INTO child_table (parent_id, other_column) VALUES (2, 'This is a third value');
DELETE FROM parent_table WHERE id = 1;
SELECT * FROM child_table;
id | parent_id | other_column
------- | -------- | --------
1 | NULL | This is a value
2 | 2 | This is another value
解説
- 上記のコードを実行すると、まず親テーブルと子テーブルが作成されます。
- 次に、親テーブルと子テーブルにデータが挿入されます。
- その後、親テーブルのレコード
id = 1
が削除されます。 - 最後に、子テーブルのレコードを確認すると、
parent_id
列がNULL
に設定されていることが確認できます。
- 上記のコードは、MySQL 8.0 で動作確認されています。
- 他のバージョンのMySQLを使用する場合は、リファレンスマニュアルを参照してください。
他の方法
トリガーを使用して、親テーブルのレコードが削除された際に、子テーブルの特定の列をNULLに設定することができます。
例
DELIMITER //
CREATE TRIGGER child_table_before_delete BEFORE DELETE ON parent_table
FOR EACH ROW
BEGIN
UPDATE child_table
SET other_column = NULL
WHERE parent_id = OLD.id;
END;
//
DELIMITER ;
- 上記のトリガーは、親テーブルのレコードが削除される前に実行されます。
- トリガーは、子テーブルの
other_column
列をNULL
に設定します。
UPDATE文を使用する
親テーブルのレコードを削除した後、UPDATE文を使用して、子テーブルの特定の列をNULLに設定することができます。
DELETE FROM parent_table WHERE id = 1;
UPDATE child_table
SET other_column = NULL
WHERE parent_id = 1;
- 次に、UPDATE文を使用して、子テーブルの
parent_id = 1
のレコードのother_column
列をNULL
に設定します。
方法の比較
方法 | メリット | デメリット |
---|---|---|
ON DELETE SET NULL | 簡単 | データ整合性が損なわれる可能性がある |
トリガー | データ整合性を維持できる | トリガーの管理が複雑になる |
UPDATE文 | 柔軟性がある | 処理が複雑になる |
- データ整合性が重要であれば、トリガーを使用するのが良いでしょう。
mysql sql foreign-keys