MySQLの用語“制約” vs“外部キー”差?
-
10-07-2019 - |
質問
MySQLドキュメントを見ていますここで、外部キーと制約の区別を整理しようとしています。 FKは 制約であると思っていましたが、ドキュメントはそれらが別々のものであるかのようにそれらについて話しているようです。
FKを作成するための構文は(一部)...
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
だから" CONSTRAINT"句はオプションです。なぜ含めるのか、含めないのか?省略した場合、MySQLは外部キーを作成しますが、制約は作成しませんか?または、「制約」のようなものですか? FKの名前にすぎないので、指定しない場合は匿名のFKを取得しますか?
説明をいただければ幸いです。
ありがとう、
イーサン
解決
はい、外部キーは制約の一種です。 MySQLには制約に対する不均等なサポートがあります:
-
PRIMARY KEY
:テーブル制約および列制約としてはい。 -
FOREIGN KEY
:テーブルの制約としてはい、ただしInnoDBおよびBDBストレージエンジンのみ。それ以外の場合は解析されますが、無視されます。 -
CHECK
:解析されますが、すべてのストレージエンジンで無視されます。 -
UNIQUE
:テーブル制約および列制約としてはい。 -
NOT NULL
:列制約としてはい。 -
DEFERRABLE
およびその他の制約属性:サポートなし。
CONSTRAINT
句を使用すると、メタデータを読みやすくしたり、制約を削除するときにその名前を使用したりするために、明示的に制約に名前を付けることができます。 SQL標準では、 CONSTRAINT
句はオプションである必要があります。省略した場合、RDBMSは自動的に名前を作成し、名前は実装次第です。
他のヒント
一般に(MySQLである必要はありません)、外部キーは制約ですが、制約は常に外部キーとは限りません。主キー制約、一意制約などを考えてください。
特定の質問に戻ると、あなたは正しいです。CONSTRAINT[記号]部分を省略すると、自動生成された名前でFKが作成されます。
現在、CREATE TABLE DDLはこの形式です-使用したUNIQUE KEYおよびFOREIGN KEY定義構文に注意してください。
CREATE TABLE my_dbschema.my_table (
id INT unsigned auto_increment PRIMARY KEY,
account_nbr INT NOT NULL,
account_name VARCHAR(50) NOT NULL,
active_flg CHAR(1) NOT NULL DEFAULT 'Y',
vendor_nbr INT NOT NULL,
create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
UNIQUE KEY uk1_my_table(account_nbr, account_name),
FOREIGN KEY fk1_my_table(vendor_nbr) REFERENCES vendor(vendor_nbr)
);
この形式では、MySQLはuk1_my_tableおよびfk1_my_tableという名前のINDEX-esを自動的に作成します。しかし、FKオブジェクト名は、my_table_ibfk_1(つまり、tablename_ibfk_N –システム定義)とは異なるものです。そのため、 ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table
は機能しません(したがって、その名前のFK dbオブジェクトがないため、イライラしてアラームを発生させます)。
constarintsの代替DDL形式です(参照: https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html ):-
CREATE TABLE my_dbschema.my_table (
id INT unsigned auto_increment PRIMARY KEY,
account_nbr INT NOT NULL,
account_name VARCHAR(50) NOT NULL,
active_flg CHAR(1) NOT NULL DEFAULT 'Y',
vendor_nbr INT NOT NULL,
create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
CONSTRAINT uk1_my_table UNIQUE KEY (account_nbr, account_name),
CONSTRAINT fk1_my_table FOREIGN KEY (vendor_nbr) REFERENCES vendor(vendor_nbr)
);
この形式では、MySQLはまだuk1_my_tableおよびfk1_my_tableという名前のINDEX-esを自動的に作成していますが、FKオブジェクト名は別のものではありません。DDLに記載されているfk1_my_tableです。したがって、 ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table
は機能しますが、同じ名前のINDEXは残されます。
そして、 ALTER TABLE my_table DROP INDEX fk1_my_table
は最初は(FKがまだドロップされていない場合)機能せず、FKで使用されているというエラーメッセージが表示されます。 DROP FKコマンドが正常に実行された場合のみ、DROP INDEXが機能します。
これが混乱の説明と解決に役立つことを願っています。
MySQLには答えられませんが、FKは制約です。データを特定の条件に強制するものはすべて制約です。制約にはいくつかの種類があり、一意、主キー、チェック、外部キーはすべて制約です。 MySQLには他にもあるのかもしれません。
コマンドで単語が許可されることもありますが、DELETEステートメントのFROMのように、読みやすくするためにまったく必要ではありません。
私が間違っていなければ、制約にはインデックスが必要なので、たとえば、外部キー制約を作成すると、MySQLも自動的にインデックスを作成します。
これは、おそらくMySQLで最も混乱しやすいtopìcです。
たとえば、「主キー」、「外部キー」、および「一意」キーは実際にはインデックスであると言われています! (MySQL公式ドキュメントはここに含まれています)
他の多くの人は、一方で、それらはむしろ制約であると言います(それは理にかなっていて、使用すると、影響を受ける列に実際に制限を課しています)。
実際にインデックスである場合、名前を付けるために制約句を使用する意味は何ですか?インデックスを作成したときにそのインデックスの名前を使用できるはずだからです
例:
...外部キーindex_name(col_name1、col_name2、...)
FOREIGN KEYがインデックスの場合、index_nameを使用してそれを処理できるはずです。ただし、できません。
ただし、インデックスではなく、インデックスを使用して実際に動作する制約がある場合、これは理にかなっています。
いずれにしても、私たちは知りません。実際、誰も知らないようです。