ラボ > FuelPHP:DB関連、MySQL

fuelphp / mysql 外部キーの制約

複雑なテーブル構成になってくると誤ってマスターを削除する可能性が高くなる…防ぐには外部キーの制約を設定しておくのが無難

作成日:2024-10-29, 更新日:2024-10-30

対象のキー

参照元と参照先で型などをきっちりと合わせておく必要がある

fuelPHP: マイグレーションファイル

<?php
namespace Fuel\Migrations;

class 〇〇〇 {
	const TABLE_NAME = '対象テーブル';
	const SEED = array(
		array(
			'key' => '〇〇〇', // 対象カラム
			'master_table' => '〇〇〇', // 参照元テーブル
			'master_colm'  => '〇〇〇', // 参照元カラム
		),
		// array(
		// 	'key' => '〇〇〇', // 対象カラム
		// 	'master_table' => '〇〇〇', // 参照元テーブル
		// 	'master_colm'  => '〇〇〇', // 参照元カラム
		// ),
	);

	public function make_constraint($key) {
		return 'foreignkey_' . self::TABLE_NAME . '_' . $key;
	}

	public function up() {
		foreach (self::SEED as $row_seed) {
			$constraint = self::make_constraint($row_seed['key']);
			\DBUtil::add_foreign_key(self::TABLE_NAME, [
				'constraint' => $constraint,
				'key' => $row_seed['key'],
				'reference' => [
					'table' => $row_seed['master_table'],
					'column' => $row_seed['master_colm'],
				],
				'on_delete' => 'RESTRICT', // 紐づくレコードがある限り、参照元の削除はNG
				'on_update' => 'RESTRICT',  // 紐づくレコードがある限り、参照元の更新はNG
				// 'on_update' => 'CASCADE',  // 紐づくレコードがあり、参照元が更新された場合、紐づくカラムも更新
			]);
		}
	}

	public function down() {
		foreach (self::SEED as $row_seed) {
			$constraint = self::make_constraint($row_seed['key']);
			\DBUtil::drop_foreign_key(self::TABLE_NAME, $constraint);
		}
	}
}

クエリ

外部キーの制約の設定

ALTER TABLE `〇〇〇` -- 対象テーブル
ADD CONSTRAINT `〇〇〇` -- 外部キー名
FOREIGN KEY (`〇〇〇`) -- 対象カラム名
REFERENCES `〇〇〇` -- 参照元になるマスターテーブル名
(`〇〇〇`) -- 参照元になるカラム名
ON DELETE RESTRICT -- 参照元を削除したときの挙動。RESTRICTは参照元の削除はNG
ON UPDATE RESTRICT -- 参照元を修正したときの挙動。RESTRICTは参照元の削除はNG
;

外部キーの制約の確認

SELECT
    TABLE_NAME, -- 対象テーブル
    COLUMN_NAME, -- 対象カラム
    CONSTRAINT_NAME, -- 外部キー名
    REFERENCED_TABLE_NAME, -- 参照元のテーブル
    REFERENCED_COLUMN_NAME -- 参照元のカラム
FROM
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
    TABLE_SCHEMA = '〇〇〇'  -- データベース名を指定
#    AND TABLE_NAME = '〇〇〇'   -- 対象のテーブル名を指定
    AND REFERENCED_TABLE_NAME IS NOT NULL;

対象テーブルで絞り込みたいとき

SELECT
    TABLE_NAME,
    COLUMN_NAME,
    CONSTRAINT_NAME,
    REFERENCED_TABLE_NAME,
    REFERENCED_COLUMN_NAME
FROM
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
    TABLE_SCHEMA = '〇〇〇'  -- データベース名を指定
    AND TABLE_NAME = '〇〇〇'   -- 対象のテーブル名を指定
    AND REFERENCED_TABLE_NAME IS NOT NULL;

外部キーの制約の削除

ALTER TABLE テーブル名 
DROP FOREIGN KEY 外部キー名; -- CONSTRAINT_NAMEの内容。外部キー名も「'」や「"」で囲む必要なし