[解決済み】外部キー制約。ON UPDATEとON DELETEを使用する場合
質問
MySQL Workbenchを使用してデータベーススキーマを設計していますが、図を書いてそれを変換できるのでとてもクールです :P
とにかく、InnoDBを使うことにしたのは、外部キーがサポートされているからです。しかし、1つ気づいたのは、外部キーにOn UpdateとOn Deleteオプションを設定できることだ。誰か、簡単な例で "Restrict", "Cascade" と set null がどこで使われるのか説明してくれますか?
例えば
user
テーブルがあり、その中に
userID
. そして、メッセージテーブルがあるとします
message
これは多対多で、2つの外部キー (同じ主キーを参照する) を持っています。
userID
での
user
テーブル)を使用することができます。この場合、On UpdateとOn Deleteのオプションの設定は何か役に立つのでしょうか?もしそうなら、どちらを選べばいいのでしょうか?もしこれが良い例でないなら、これらがどのように有用であるかを説明する良い例を考えていただけませんか?
ありがとうございます。
解決方法は?
データベースに制約をかけることを躊躇しないでください。データベースの一貫性を保つことができ、それがデータベースを使用する良い理由の1つです。特に、複数のアプリケーションから要求がある場合(または、1つのアプリケーションで、異なるソースを使用するダイレクトモードとバッチモードがある場合)には、なおさらです。
MySQLでは、postgreSQLのような高度な制約はありませんが、少なくとも外部キー制約はかなり高度なものです。
例えば、ある会社のテーブルと、その会社の人を含むユーザー・テーブルを例にとります。
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
を見てみましょう。 オンアップデート 節があります。
- 更新時の制限 : デフォルトの もし、COMPANYテーブルのcompany_idを更新しようとした場合、少なくとも1人のUSERがこの会社にリンクしていれば、エンジンはその操作を拒否します。
- 更新時に何もしない : RESTRICTと同じです。
- 更新カスケード時 : 通常、最も良いもの COMPANYテーブルの行のcompany_idを更新すると、エンジンはそのCOMPANYを参照しているすべてのUSERの行でそれを更新します(ただし、USERテーブルでトリガーを有効にしていない場合は警告が表示されます)。エンジンが変更を追跡してくれるので、良いですね。
- 更新時にNULLを設定 COMPANY テーブルの行の company_id を更新すると、エンジンは関連する USER の company_id を NULL に設定します (USER company_id フィールドで利用可能なはずです)。更新時にこのような処理を行う面白い方法は見当たりませんが、間違っているかもしれません。
そして、今度は ON DELETE の側です。
- 削除制限について : デフォルトの もし、COMPANYテーブルのcompany_idを削除しようとした場合、少なくとも1人のユーザーがその会社にリンクしていれば、エンジンはその操作を拒否しますので、あなたの命を救うことができます。
- 削除時に何もしない RESTRICTと同じです。
- 削除カスケード時 : 危険 COMPANYテーブルの会社の行を削除すると、関連するUSERも削除されます。これは危険ですが、セカンダリテーブルの自動クリーンアップに使用できます(したがって、COMPANY<->USERの例では確実に使用できません)。
- 削除時にNULLを設定 : 握り COMPANY行を削除した場合、関連するUSERは自動的にNULLになります。例えば、あるコンテンツの作者としてユーザーをアプリケーションに残す必要がある場合、会社を削除しても問題はありません。
通常、私のデフォルトは
削除時 制限時 更新時 カスケード
.いくつかの
ON DELETE CASCADE
はトラックテーブル (ログ - すべてのログではない - など) 用に、そして
ON DELETE SET NULL
マスターテーブルが、USERテーブルに対するJOBテーブルのように、外部キーを含むテーブルの「単純な属性」である場合。
編集
久しぶりの書き込みです。今になって、一つ重要な警告を付け加えておこうと思います。MySQL には、カスケードに関する 1 つの大きな制限事項が文書化されています。 カスケードはトリガーを発射しない . ですから、もしあなたがそのエンジンに十分な自信を持ってトリガーを使っていたのなら、カスケード制約を避けるべきでしょう。
MySQLトリガーは、SQLステートメントによるテーブルの変更に対してのみ起動します。ビューの変更や、SQLステートメントをMySQLサーバーに送信しないAPIによって行われたテーブルの変更では起動しません。
==> 最終編集の下をご覧ください、このドメインで物事が動いています。
<ブロッククオートトリガーは外部キー操作では起動しません。
そして、これはいつか修正されるとは思っていません。外部キー制約は InnoDb ストレージで管理され、トリガーは MySQL SQL エンジンで管理されます。両者は分離されています。Innodbは制約管理を持つ唯一のストレージで、いつかストレージエンジンで直接トリガーを追加するかもしれないし、しないかもしれない。
しかし、トリガーの実装の貧弱さと、非常に便利な外部キー制約のサポートのどちらを選ぶべきか、私自身の意見を持っています。そして、一度データベースの一貫性に慣れてしまえば、PostgreSQLを好きになることでしょう。
2017/12-MySQLについてこのEditを更新しました。
コメントで @IstiaqueAhmed が述べているように、この件に関する状況は変化しています。そのため、リンクをたどって本当の最新状況を確認してください(今後、また変わる可能性もあります)。
関連
-
[解決済み] エラー 1044 (42000)。データベース 'db' へのユーザー ''@'localhost'' のアクセスが拒否されました。
-
[解決済み] #1136 - 列数が 1 行目の値数と一致しません。
-
[解決済み] SQL エラー - テーブルの定義が正しくありません; auto カラムは 1 つしか存在できません。
-
[解決済み] エラーコードです。1215. 外部キー制約を追加できません (外部キー)
-
[解決済み] T-SQLを使用して外部キー制約を一時的に無効にするにはどうすればよいですか?
-
[解決済み] 外部キー制約のあるテーブルを切り捨てるには?
-
[解決済み] FOREIGN KEY制約を導入すると、サイクルや複数のカスケード・パスが発生する可能性があります - なぜですか?
-
[解決済み】既存テーブルへの外部キー追加
-
[解決済み] MySQLの外部キー制約、カスケード削除
-
[解決済み] 外部キー制約をバイパスしてmysqlを強制的にドロップする
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】MySQL: グループ関数の無効な使用
-
[解決済み】autoカラムは1つしか存在できない
-
[解決済み】mysqlが内部または外部のコマンド、操作可能なプログラムまたはバッチとして認識されない。
-
[解決済み] 1030 ストレージエンジンからエラー28が発生しました
-
[解決済み] MySql テーブル、エラー#1064 & エラー#1068 複数の主キーが定義されている [終了] 。
-
[解決済み] このMySQLエラー Incorrect column specifier for column COLUMN NAMEを回避するにはどうしたらよいですか?
-
[解決済み] MySQL エラー 1241。オペランドには1つのカラムが含まれている必要があります。
-
[解決済み] 「他のデータベースへのクエリを無視する」コマンドライン
-
[解決済み] ルートユーザーでログインしているのに、phpMyAdminがデータベースを作成する権限がないと言う
-
[解決済み] MongoDBのようにMySQLにもTTLがあるのでしょうか?