web-dev-qa-db-ja.com

MySQLの用語「制約」と「外部キー」の違いは?

MySQLのドキュメント here を見て、外部キーと制約の違いを整理しようとしています。私はFKが制約だったと思いましたが、ドキュメントはそれらが別個のものであるかのようにそれらについて話しているようです。

FKを作成するための構文は(部分的に)...

[CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name,...)

したがって、「CONSTRAINT」句はオプションです。なぜ含めるか、含めないのですか?省略した場合、MySQLは制約ではなく外部キーを作成しますか?それとも、「CONSTRAINT」はFKの名前にすぎないので、指定しないと匿名のFKになりますか?

明確化をいただければ幸いです。

おかげで、

イーサン

44
Ethan

はい、外部キーは一種の制約です。 MySQLの制約に対するサポートは均一ではありません。

  • PRIMARY KEY:はい、テーブル制約と列制約として。
  • FOREIGN KEY:テーブルの制約としてはい、ただしInnoDBおよびBDBストレージエンジンでのみ。それ以外の場合は解析されますが無視されます。
  • CHECK:解析されましたが、すべてのストレージエンジンで無視されました。
  • UNIQUE:はい、テーブル制約および列制約として。
  • NOT NULL:はい、列の制約として。
  • DEFERRABLEおよびその他の制約属性:サポートなし。

CONSTRAINT句を使用すると、メタデータを読みやすくするため、または制約を削除するときに名前を使用するために、制約に明示的に名前を付けることができます。 SQL標準では、CONSTRAINT句はオプションです。省略した場合、RDBMSは自動的に名前を作成し、名前は実装次第です。

58
Bill Karwin

一般的に(MySQLは不要)、外部キーは制約ですが、制約は常に外部キーであるとは限りません。主キー制約、一意の制約などについて考えてください。

特定の質問に戻ると、あなたは正解です。CONSTRAINT[シンボル]の部分を省略すると、自動生成された名前のFKが作成されます。

9
Dan C.

現在のところ、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が機能します。

これが混乱を説明し、解決に役立つことを願っています。

3
RxBx

私が間違っていない場合、制約にはインデックスが必要なので、たとえば、外部キー制約を作成すると、MySQLは自動的にインデックスも作成します。

1
Mario Juárez

MySQLには答えられませんが、FKは制約です。データを特定の条件に強制するものはすべて制約です。制約にはいくつかの種類があり、一意、主キー、チェック、および外部キーはすべて制約です。 MySQLには他にもあるかもしれません。

場合によっては、コマンドで単語を使用できますが、DELETEステートメントのFROMのように、読みやすくするために完全に必須というわけではありません。

1
Mark Brady

これはおそらく、MySQLで最も混乱するトピックです。

たとえば、 'PRIMARY KEY'、 'FOREIGN KEY'、 'UNIQUE'キーは実際にはインデックスであると多くの人が言っています! (MySQLの公式ドキュメントはここに含まれています)

一方、他の多くの人は、それらはむしろ制約であると言っています(使用すると、影響を受ける列に実際に制限を課すことになり、理にかなっています)。

それらが実際にインデックスである場合、作成時にそのインデックスの名前を使用できるはずなので、名前を付けるために制約句を使用するポイントは何ですか?

例:

... FOREIGN KEY index_name(col_name1、col_name2、...)

FOREIGN KEYがインデックスの場合、index_nameを使用してそれを処理できるはずです。ただし、できません。

しかし、それらがインデックスではなく、インデックスを使用して機能する実際の制約である場合、これは理にかなっています。

いずれにせよ、私たちは知りません。実際、誰も知らないようです。

0
Johann