MySQL 外部キー制約の例の説明

MySQL 外部キー制約の例の説明

MySQL の外部キー制約は、2 つのテーブル間のリンクを確立するために使用されます。 1 つのテーブルが変更されると、もう 1 つのテーブルも変更されます。この機能の主な目的は、テーブル データの一貫性と整合性を確保することです。
外部キーによって関連付けられた 2 つのテーブルの場合、関連フィールドの主キーが配置されているテーブルは主テーブル (親テーブルとも呼ばれます) であり、外部キーが配置されているテーブルは副テーブル (子テーブルとも呼ばれます) です。外部キーを定義するときは、いくつかのルールに従う必要があります。

1. 親テーブルはデータベース内に既に存在しているか、現在作成中のテーブルである必要があります。後者の場合、親テーブルと子テーブルは同じテーブルです。このようなテーブルは自己参照テーブルと呼ばれ、この構造は自己参照と呼ばれます。
2. 親テーブルに主キーを定義する必要があります。
3. 主キーには null 値を含めることはできませんが、外部キーには null 値を含めることができます。つまり、外部キーの null 以外の値がすべて指定された主キーに表示されている限り、この外部キーの内容は正しいことになります。
4. 外部キーの列数は、親テーブルの主キーの列数と同じである必要があります。
5. 外部キーの列のデータ型は、親テーブルの主キーの対応する列のデータ型と同じである必要があります。これらはすべてかなり一般的なので、いくつか例を見てみましょう。

mysql:yeyztest ::>>テーブルfk_test_1(を作成します 
 -> id int not null 主キー auto_increment,
 -> name varchar() デフォルト '');
クエリは正常、行は影響を受けました (0.10 秒)

mysql:yeyztest ::>>テーブルfk_test_2(を作成します
 -> id int not null 主キー auto_increment,
 -> uid int、 
 -> 外部キー f​​k_uid(uid) は fk_test_1(id) を参照します。
クエリは正常、行は影響を受けました (0.06 秒)

ここでは、fk_test_1 と fk_test_2 の 2 つのテーブルを作成します。fk_test_2 の uid 列に外部キーを設定し、fk_test_1 のテーブルの id 列を関連付けます。ここでは、fk_test_1 が親テーブルで、fk_test_2 が子テーブルであることは明らかです。次に、データ挿入実験を行います。

mysql:yeyztest ::>>fk_test_1 に値 (,'aaa'),(,'bbb') を挿入します。
クエリは正常、行は影響を受けました (0.00 秒)
レコード: 重複: 警告: 

mysql:yeyztest ::>>fk_test_1 から * を選択します。
+----+------+
| ID | 名前 |
+----+------+
| | ああ |
| | bbb |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>fk_test_2 に値 (,),(,); を挿入します。
クエリは正常、行は影響を受けました (0.00 秒)
レコード: 重複: 警告: 

mysql:yeyztest ::>>fk_test_2 の値に挿入します(,);
クエリは正常、行は影響を受けました (0.00 秒)


mysql:yeyztest ::>>fk_test_2 の値に挿入します(,);  
エラー (): 子行を追加または更新できません: 外部キー制約が失敗しました (`yeyztest`.`fk_test_2`、制約 `fk_test_2_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `fk_test_1` (`id`))

まず、メイン テーブルに id=1 と id=2 の 2 つのデータを挿入し、次に子テーブルにデータを挿入します。子テーブルは、uid=1 と uid=2 のデータを正常に挿入できますが、uid=3 のデータの挿入は失敗します。つまり、デフォルトでは、子テーブルに挿入する場合、挿入される外部キー関連フィールド値は、親テーブルの関連列に含まれる値である必要があります。ここでのデフォルトの状況に注意してください。これについては後で説明します。

削除状況を見てみましょう。

mysql:yeyztest ::>>fk_test_2 から * を選択します。
+----+------+
| ID | ユーザID |
+----+------+
| | |
| | |
| | |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>id=; の fk_test_2 から削除します。
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_1 から * を選択します。  
+----+------+
| ID | 名前 |
+----+------+
| | ああ |
| | bbb |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>id=; の fk_test_1 から削除します。 
エラー (): 親行を削除または更新できません: 外部キー制約が失敗しました (`yeyztest`.`fk_test_2`、制約 `fk_test_2_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `fk_test_1` (`id`))

子テーブル fk_test_2 で削除しても問題ないことがわかりますが、親テーブル fk_test_1 で削除すると、id=1 の値が削除できないことがわかります。 理由は、外部キー制約があるためです。 つまり、デフォルトでは、親テーブルから削除する場合、子テーブルですでに従属関係にある列値を直接削除することはできません。ここではデフォルトに注意してください。これについては以下で説明します。

削除に失敗したので、更新を試みてください。

mysql:yeyztest ::>>fk_test_1 を更新し、id= を設定します。id=;   
エラー (): 親行を削除または更新できません: 
外部キー制約が失敗する (`yeyztest`.`fk_test_2`、 
制約 `fk_test_2_ibfk_1` 外部キー (`uid`) 参照 `fk_test_1` (`id`))

mysql:yeyztest ::>>fk_test_1 を更新し、name='ccc' を設定します (id=;) 
クエリは正常、行は影響を受けました (0.00 秒)
一致した行: 変更: 警告:

親テーブルの主キー列の更新はまだ正常に実行できないことがわかりますが、他の列の更新は正常に実行できます。

この時点で、外部キーの存在はデータの整合性と統一性を保証するためのものであることはすでにわかっていますが、小さな問題も発生します。つまり、子テーブルに依存する親テーブルの列は削除できません。これは私たちが望んでいることではありません。一部のデータは確かに期限切れになり、削除する必要がありますが、この時点で何をすべきでしょうか。

上記のテストでは、繰り返し言及しましたが、デフォルトでは、外部キーの削除および更新ルールを設定していませんでした。ここで、MySQL は、最も厳しいルールである制限を使用するのに役立ちました。実際には、他にもいくつかのルールがあり、それらはすべてここにリストされています。

  • 親テーブルを削除します。

カスケード、null 設定、アクションなし、制限

  • 親テーブルを更新します。

カスケード、null 設定、アクションなし、制限

  • 制限はデフォルトの操作であり、親テーブルは子テーブルが依存する外部キー列を削除または変更できないことを意味します。これは最も安全な設定です。
  • カスケードとは、親テーブルが削除されると、子テーブルのレコードも直接削除されることを意味します。これは最も危険な設定です。
  • null を設定すると、親テーブルが削除されたときに、子テーブルは null 値で処理されます。
  • アクションなしとは、親テーブルが削除されても、子テーブルには変更が加えられないことを意味します。

関連付けを設定するための構文は次のとおりです。

テーブル名を変更し、制約 FK_ID 外部キー (外部キー フィールド名) を追加して、外部テーブル名 (主キー フィールド名) を参照します。
[削除時に {カスケード | null を設定 | アクションなし | 制限}]
[更新時に {カスケード | null を設定 | アクションなし | 制限}]

それでは、カスケードケースから始めて、他の 3 つのケースをテストしてみましょう。

mysql:yeyztest ::>>fk_test_1 から * を選択します。
+----+------+
| ID | 名前 |
+----+------+
| | ccc |
| | bbb |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>fk_test_2 から * を選択します。
+----+------+
| ID | ユーザID |
+----+------+
| | |
| | |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>テーブル fk_test_2\G の作成を表示
************************** 1. 行 ****************************
  テーブル: fk_test_2
テーブルの作成: CREATE TABLE `fk_test_2` (
 `id` int() NOT NULL AUTO_INCREMENT、
 `uid` int() デフォルト NULL,
 主キー (`id`)、
 キー `fk_uid` (`uid`),
 制約 `fk_test_2_ibfk_1` 外部キー (`uid`) 参照 `fk_test_1` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= デフォルト CHARSET=utf8
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>テーブルfk_test_2を変更し、外部キーfk_test_2_ibfk_1を削除します。
クエリは正常、行は影響を受けました (0.02 秒)
レコード: 重複: 警告: 

mysql:yeyztest ::>>テーブルfk_test_2を変更し、制約fk_uidを追加し、外部キー(uid)は削除カスケードでfk_test_1(id)を参照します。
クエリは正常、行は影響を受けました (0.03 秒)
レコード: 重複: 警告: 

#######################################
####ここで親テーブル id= のレコードを削除し、子テーブルの結果を確認します###
#######################################
mysql:yeyztest ::>>id=; の fk_test_1 から削除します。
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_1 から * を選択します。
+----+------+
| ID | 名前 |
+----+------+
| | ccc |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>fk_test_2 から * を選択します。
+----+------+
| ID | ユーザID |
+----+------+
| | |
+----+------+
 セット内の行数 (0.00 秒)

最初は親テーブルの値にid=1とid=2の値が含まれ、子テーブルの値にuid=2とuid=1の値が含まれていることがわかります。親テーブルのid=2の値を削除すると、子テーブルのuid=2の値も直接削除されます。これがカスケードの役割、つまりカスケード削除です。

set null の場合を見てみましょう。

mysql:yeyztest ::>>テーブルfk_test_2を変更し、外部キーfk_uidを削除します。   
クエリは正常、行は影響を受けました (0.02 秒)
レコード: 重複: 警告: 

mysql:yeyztest ::>>テーブル fk_test_2 を変更し、制約 `fk_uid` 外部キー (`uid`) 参照 `fk_test_1` (`id`) を追加し、削除時に null を設定します。
クエリは正常、行は影響を受けました (0.03 秒)
レコード: 重複: 警告: 

mysql:yeyztest ::>>id=; の fk_test_1 から削除します。
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_1から*を選択します。
空のセット (0.00 秒)

mysql:yeyztest ::>>fk_test_2から*を選択します。
+----+------+
| ID | ユーザID |
+----+------+
| | NULL |
+----+------+
 セット内の行数 (0.00 秒)

set null を設定した後、親テーブルで id=1 の値を削除すると、子テーブルの uid の値が null になり、レコードが削除されないことがわかります。

アクションなしの状況も同様ですが、子テーブル内のレコードは変更されません。

上記は親テーブルを削除する操作です。親テーブルが更新されると、子テーブルも上記の 4 つの状況を選択できますが、基本的には削除と同じなので、ここでは繰り返しません。ご興味があれば、ぜひご自身でお試しください。

最後に、子テーブルの外部キー列には null 値が含まれる可能性があることに注意してください。

mysql:yeyztest ::>>fk_test_1 の値に挿入します(,);
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_2から*を選択します。   
+----+------+
| ID | ユーザID |
+----+------+
| | NULL |
+----+------+
 セット内の行数 (0.00 秒)

mysql:yeyztest ::>>fk_test_2 に値を挿入します ​​(,NULL);
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_2 に値を挿入します ​​(,NULL);
クエリは正常、行は影響を受けました (0.00 秒)

mysql:yeyztest ::>>fk_test_2 から * を選択します。
+----+------+
| ID | ユーザID |
+----+------+
| | NULL |
| | NULL |
| | NULL |
+----+------+
 セット内の行数 (0.00 秒)

上記はMySQL外部キー制約の例の説明の詳細な内容です。MySQL外部キー制約の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL に外部キー制約を追加する具体的な方法
  • MySQL 外部キー制約 (FOREIGN KEY) ケースの説明
  • MySQL 外部キー制約とテーブル関係の概要
  • MySQL 外部キー制約の詳細な説明
  • 外部キー制約を持つテーブルデータを削除する MySQL メソッドの紹介
  • MySQL テーブルを削除するときに外部キー制約を無視するシンプルな実装
  • MySQL 子テーブルで外部キー制約チェックを無効にする方法
  • MySQL で外部キー制約を作成および削除する方法

<<:  Alibaba Cloud Server Linux システムは Tomcat を構築して Web プロジェクトを展開します

>>:  JavaScript 関数構文の説明

推薦する

MySQL information_schema データベースの詳細な説明

1. 概要information_schema データベースは performance_schema...

MySQLの浅いエントリと深いエグジットの原則についての簡単な説明

目次1. ページの概要2. 下限と上限3. ページディレクトリを使用する4. ページの実際の外観4....

マルチコア CPU を使用して Linux コマンドを高速化する方法 (GNU Parallel)

非常に大量のデータ(数百 GB)を計算する必要があったことはありますか?または、その内部を検索したり...

要素のel-tree複数選択ツリー(チェックボックス)親子ノードの関連付けが関連付けられていません

属性チェック-厳密公式ドキュメントでは、チェックボックスが表示されるときに親項目と子項目を互いに関連...

Vue3の状態管理の使用方法の詳細な説明

目次背景提供/注入共有状態の抽出データを提供するデータの挿入まとめ反応的な共有状態の抽出共有状態の使...

MySQL の準同期レプリケーションについての簡単な説明

導入MySQL はレプリケーションを通じてストレージ システムの高可用性を実現します。現在、MySQ...

DockerでJenkinsをインストールし、初期プラグインのインストール失敗の問題を解決する

Jenkins をインストールした後、プラグインの初期ダウンロードが常に失敗し、インストールが失敗し...

Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明

Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明注:以下のプ...

HTMLノードの追加と削除の簡単な例

HTML ノードの追加と削除の簡単な例 HTML ノードの追加と削除の簡単な例<input t...

MySQL 5.5.27 winx64 のインストールと設定方法のグラフィックチュートリアル

1. インストールパッケージMYSQLサービスダウンロードアドレス:MySQL公式サイトからダウンロ...

ナビゲーションデザインと情報アーキテクチャ

<br />ナビゲーションについて話すときは、ほとんどの場合、ナビゲーションがコンテンツ...

Linux での MySQL 5.7 の導入とリモート アクセス構成

前書き: 最近、私はパートナーとチームを組んで .NET Core プロジェクトに取り組む予定です。...

VueはSplitを使用して、ユニバーサルドラッグアンドスライドパーティションパネルコンポーネントをカプセル化します。

目次序文始める基本レイアウトデータバインディングイベントバインディング最適化ジッター問題を最適化する...

Docker-Composeコマンドの使い方の詳しい説明

Docker コンテナはさまざまな方法で管理およびデプロイできます。 Docker コマンドを直接使...

MySQL の制限パフォーマンス分析と最適化

1. 結論構文: 制限オフセット、行結論: 同じ行条件では、オフセット値が大きいほど、limitステ...