Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
PRIMARY KEY / FOREIGN KEY
主キーはテーブルの行を一意に識別する列、外部キーは別テーブルの主キーを参照する列です。テーブル間のリレーションシップを定義します。
構文
-- 主キーを設定します(列定義内)。
列名 データ型 PRIMARY KEY
-- 主キーを設定します(テーブル制約として)。
PRIMARY KEY (列名)
-- 複合主キーを設定します。
PRIMARY KEY (列名1, 列名2)
-- 外部キーを設定します。
FOREIGN KEY (列名) REFERENCES 参照テーブル名 (参照列名)
ON DELETE アクション
ON UPDATE アクション
構文一覧
| 構文 | 概要 |
|---|---|
| PRIMARY KEY | テーブルの主キーを設定します。NOT NULLかつUNIQUEが自動的に適用されます。テーブルに1つだけ設定できます。 |
| PRIMARY KEY (列1, 列2) | 複数列を組み合わせた複合主キーを設定します。中間テーブル(多対多の関係)によく使われます。 |
| FOREIGN KEY...REFERENCES | 別テーブルの列を参照する外部キーを設定します。参照整合性を保証します。 |
| ON DELETE CASCADE | 参照先の行が削除されたとき、参照元の行も自動的に削除します。 |
| ON DELETE SET NULL | 参照先の行が削除されたとき、外部キー列をNULLに設定します。 |
| ON DELETE RESTRICT | 参照元に行が存在する場合、参照先の行の削除を禁止します(デフォルト)。 |
| ON UPDATE CASCADE | 参照先のキー値が変更されたとき、参照元も自動的に更新します。 |
サンプルコード
-- 顧客テーブル(参照される側)を作成します。
CREATE TABLE customers (
customer_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (customer_id)
);
-- 注文テーブル(外部キーを持つ側)を作成します。
CREATE TABLE orders (
order_id INT NOT NULL AUTO_INCREMENT,
customer_id INT NOT NULL,
total INT NOT NULL,
PRIMARY KEY (order_id),
CONSTRAINT fk_orders_customer
FOREIGN KEY (customer_id)
REFERENCES customers (customer_id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
-- 複合主キーを使った中間テーブル(多対多)を作成します。
CREATE TABLE order_products (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (order_id) REFERENCES orders (order_id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE RESTRICT
);
実行結果
-- 外部キー制約に違反した INSERT を行った場合のエラー例(MySQL) -- ERROR 1452 (23000): Cannot add or update a child row: -- a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` -- FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`)) -- ON DELETE RESTRICT の場合、参照されている行を削除しようとしたエラー例 -- ERROR 1451 (23000): Cannot delete or update a parent row: -- a foreign key constraint fails
データベース別の書き方
『PRIMARY KEY』と『FOREIGN KEY』の基本構文は主要なデータベースで共通して使用できます。
CREATE TABLE orders (
order_id INT NOT NULL,
customer_id INT NOT NULL,
PRIMARY KEY (order_id),
FOREIGN KEY (customer_id) REFERENCES customers (customer_id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
自動連番の主キー定義はデータベースによって異なります。MySQL は『AUTO_INCREMENT』、PostgreSQL は『SERIAL』、SQL Server は『IDENTITY』、SQLite は『INTEGER PRIMARY KEY』を使用します。
-- MySQL order_id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (order_id) -- PostgreSQL order_id SERIAL PRIMARY KEY -- SQL Server order_id INT NOT NULL IDENTITY(1,1), PRIMARY KEY (order_id) -- SQLite order_id INTEGER PRIMARY KEY
『ON DELETE』『ON UPDATE』のアクション(『CASCADE』『SET NULL』『RESTRICT』)は主要なデータベースで共通して使用できます。ただし、SQLite では外部キー制約がデフォルトで無効になっており、『PRAGMA foreign_keys = ON;』で有効化する必要があります。
-- SQLite(外部キー制約を有効にする) PRAGMA foreign_keys = ON;
概要
『PRIMARY KEY』は行を一意に識別するための列です。一般的には整数の連番(AUTO_INCREMENT)を使いますが、メールアドレスや商品コードのような自然キーを使う場合もあります。複合主キーは複数列の組み合わせで一意性を保証します。
『FOREIGN KEY』を設定すると、参照先に存在しない値を外部キー列に登録しようとした際にエラーになります。これを参照整合性といいます。『ON DELETE CASCADE』を使うと、親レコードを削除すると子レコードが自動的に削除されるため、手動でのクリーンアップが不要になります。
テーブル作成の基本は『CREATE TABLE』を、その他の列制約については『NOT NULL / UNIQUE / DEFAULT』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。