外部キー(Foreign Key)は、データベースにおける重要な概念で、リレーショナルデータベースのテーブル間の関連性(=リレーション)を表現するために使用される仕組みです。
このページでは外部キーの意味と概念、システム的に押さえておきたいポイントをIT初心者向けにわかりやすく3分で解説します。
システムエンジニア(特にデータベースを扱う方)を目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。
外部キーとは(Foreign Key)
外部キー(Foreign Key)は、リレーショナルデータベースのテーブル間の関連性(=リレーション)を表現するために使用されるデータベースの仕組みです。
ある種の「つながり」を示すものと考えていただくと良いかもしれません。
例えば、以下のテーブルで説明すると、2つのテーブルには「氏名」という項目につながりがありますよということを外部キーで示すことができます。
より具体的に外部キーのイメージをより深められるよう、図書館のシステムを構築する場合を考えてみます。
このシステムには、「本テーブル」と「借り手テーブル」があり、それぞれのテーブルには以下のような情報を保持することとします。
さて、このときある本が誰によって借りられているかを追跡したいとします。上記のカラムからでは、本テーブルに「借り手」を一意に示す項目が存在しないので、今のままでは追跡は不可能です。
この課題を解決するために(ある本が誰によって借りられているか?を追跡できるように)「本テーブル」に「借り手のID」を追加します。
この「借り手のID」が「外部キー」になります。この外部キーを辿ることで、「本テーブル」と「借り手テーブル」をつなげることができるということ。基本的な考え方としては非常に簡単です。
BookID | Title | Author | BorrowerID |
---|---|---|---|
1 | Book A | Author X | 1 |
2 | Book B | Author Y | 2 |
3 | Book C | Author Z | NULL |
BorrowerID | Name | Address |
---|---|---|
1 | John Doe | 123 Main St. |
2 | Jane Smith | 456 Elm St. |
実際にMySQLを利用して、外部キーを設定したテーブルを定義してみます。
-- 本テーブル CREATE TABLE Book ( BookID INT AUTO_INCREMENT, Title VARCHAR(255), Author VARCHAR(255), BorrowerID INT, PRIMARY KEY (BookID), FOREIGN KEY (BorrowerID) REFERENCES Borrower(ID) ); -- 借り手テーブル CREATE TABLE Borrower ( ID INT AUTO_INCREMENT, Name VARCHAR(255), Address VARCHAR(255), PRIMARY KEY (ID) );
このSQL文では、FOREIGN KEY (BorrowerID) REFERENCES Borrower(ID)
という部分が外部キー制約を設定しています。これにより、「本」テーブルのBorrowerIDは、「借り手」テーブルのIDを参照することが明示されています。
外部キーの役割
何となく外部キーのイメージがついたところで、外部キーの役割を重要なポイントに絞って以下3点解説します。
1つ1つを正しく理解することでより具体的に外部キーのイメージが深まっていくことでしょう。
外部キーとは①:関連性の表現
外部キーの主な特性と役割の一つは、「関連性の表現」です。
例として先ほどの「本テーブル」と「借り手テーブル」を考えてみます。
BookID | Title | Author | BorrowerID |
---|---|---|---|
1 | Book A | Author X | 1 |
2 | Book B | Author Y | 2 |
3 | Book C | Author Z | NULL |
BorrowerID | Name | Address |
---|---|---|
1 | John Doe | 123 Main St. |
2 | Jane Smith | 456 Elm St. |
これらのテーブルは、本と借り手の関連性を表現するために外部キーを使用しています。具体的には、「本テーブル」の中にある「BorrowerID」というフィールドが、「借り手テーブル」の「BorrowerID」と関連付けられています。
これにより、個々の本がどの借り手によって借りられているかを示すことができます。例えば、BookID 1の本はBorrowerID 1の借り手によって借りられていることを表現することができます。
外部キーとは②:データの整合性の保持
外部キーを利用することで以下の2点がDBMSにより保証されます。
- 参照の整合性
外部キー制約により、本テーブルのBorrowerIDが借り手テーブルのBorrowerIDと一致していることが保証されます。これにより、存在しない借り手IDを参照することが防止されます。 - 削除および更新の制限
外部キー制約により、借り手テーブルの特定のBorrowerIDが削除または更新される際に、それに関連する本テーブルのレコードも同様に削除または更新されるか制限されます。これにより、関連データの整合性が保たれます。
実際にサンプルデータを先ほどの2つのテーブルに投入して実演してみます。
-- 借り手テーブル (Borrower) のサンプルデータのINSERT文 INSERT INTO Borrower (Name, Address) VALUES ('John Doe', '123 Main St.'), ('Jane Smith', '456 Elm St.'); -- 本テーブル (Book) のサンプルデータのINSERT文 INSERT INTO Book (Title, Author, BorrowerID) VALUES ('Book A', 'Author X', 1), ('Book B', 'Author Y', 2), ('Book C', 'Author Z', NULL);
参考 INSERT文
BookID | Title | Author | BorrowerID |
---|---|---|---|
1 | Book A | Author X | 1 |
2 | Book B | Author Y | 2 |
3 | Book C | Author Z | NULL |
BorrowerID | Name | Address |
---|---|---|
1 | John Doe | 123 Main St. |
2 | Jane Smith | 456 Elm St. |
参照の整合性
外部キー制約により、本テーブルのBorrowerIDが借り手テーブルのBorrowerIDと一致していることが保証されます。これにより、存在しない借り手IDを参照することが防止されます。
-- 存在しない借り手ID 3を参照する本を追加しようとする INSERT INTO Book (Title, Author, BorrowerID) VALUES ('Book D', 'Author W', 3); /* ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`sampledb`.`book`, CONSTRAINT `book_ibfk_1` FOREIGN KEY (`BorrowerID`) REFERENCES `borrower` (`ID`)) */
この操作はエラーを引き起こし、外部キー制約違反が発生します。存在しない借り手ID 3を参照しようとしているためです。
削除および更新の制限
外部キー制約により、借り手テーブルの特定のBorrowerIDが削除または更新される際に、それに関連する本テーブルのレコードも同様に削除または更新されるか制限されます。これにより、関連データの整合性が保たれます。
-- 借り手ID 1の借り手を削除しようとする DELETE FROM Borrower WHERE ID = 1; /* ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`sampledb`.`book`, CONSTRAINT `book_ibfk_1` FOREIGN KEY (`BorrowerID`) REFERENCES `borrower` (`ID`)) */
この操作も同様なエラー(外部キー制約違反)を発生させます。借り手ID 1に関連付けられた本が存在するため、制約によって削除が制限されています。
参考 DELETE文
外部キーとは③:参照の追跡
外部キーを付与することで、外部キー制約によって関連するデータを特定することができます。
具体的には、本テーブルのBorrowerIDが借り手テーブルのIDを参照しているため、どの本がどの借り手に関連付けられているかを確認できます。
-- 本テーブルと借り手テーブルを結合し、本のタイトル、著者、借り手の名前を取得する。 SELECT b.Title, b.Author, br.Name FROM Book b JOIN Borrower br ON b.BorrowerID = br.ID; /* 結果 Book AはJohn Doeによって、Book BはJane Smithによって借りられていることがわかる。 +--------+----------+------------+ | Title | Author | Name | +--------+----------+------------+ | Book A | Author X | John Doe | | Book B | Author Y | Jane Smith | +--------+----------+------------+ */
このように、外部キー制約を使用して参照の追跡を行うことで、関連するデータを特定することができます。これはデータの一貫性を保持する上で役立ちます。
SQLを1から学習したい方は
SQLやデータベースの仕組みを1から学習したい方(学び直したい方)向けに、現役エンジニア達のスキルを結集して 完全無料 のSQL教材を作成しました。
SQLは決して難しい技術ではないので、エンジニアであれば「当たり前のように」扱えて当然かも・・・?
とはいえ、案外SQLをちゃんと使ったことがない人も多いはずです。この機会に是非一度ご覧になってみてください。