24

MySQL でテーブルを作成しました。

CREATE TABLE actions ( A_id int NOT NULL AUTO_INCREMENT,
type ENUM('rate','report','submit','edit','delete') NOT NULL,
Q_id int NOT NULL,
U_id int NOT NULL,
date DATE NOT NULL,
time TIME NOT NULL,
rate tinyint(1),
PRIMARY KEY (A_id),
CONSTRAINT fk_Question FOREIGN KEY (Q_id) REFERENCES questions(P_id),
CONSTRAINT fk_User FOREIGN KEY (U_id) REFERENCES users(P_id));

これにより、必要なテーブルが正常に作成されました (ただし、「DESCRIBE actions;」コマンドを実行すると、外部キーが MUL 型のキーであることがわかりましたが、これが何を意味するのかわかりません)。ただし、質問テーブルまたはユーザー テーブルに存在しない Q_id または U_id を入力しようとすると、MySQL はこれらの値を許可します。

私は何を間違えましたか?外部キーを持つテーブルが無効なデータを受け入れないようにするにはどうすればよいですか?

更新 1

最後に追加TYPE=InnoDBすると、エラーが発生します。

エラー 1005 (HY000): テーブル './quotes/actions.frm' を作成できません (errno: 150)

なぜそれが起こるのでしょうか?

更新 2

機能的な外部キーを使用してデータの整合性を確保することが重要であると言われましたが、MySQL では InnoDB を使用しないでください。おすすめは何ですか?

4

10 に答える 10

58

デフォルトのストレージ エンジンは、外部キー制約を無視する MyISAM だと思います。外部キーの宣言を暗黙のうちに受け入れますが、制約を保存したり、その後強制したりしません。

ただし、外部キー用に宣言した列に暗黙的にインデックスを作成します。MySQL では、" KEY" は " " の同義語ですINDEX。それが DESCRIBE 出力に示されているものです: インデックスですが、制約ではありません。

制約がないため、今すぐテーブルに無効な値を挿入できます。参照整合性を強制する制約を取得するには、 InnoDB ストレージ エンジンを使用する必要があります。

CREATE TABLE actions (
  A_id int NOT NULL AUTO_INCREMENT,
  ...
  CONSTRAINT fk_Question FOREIGN KEY (Q_id) REFERENCES questions(P_id),
  CONSTRAINT fk_User FOREIGN KEY (U_id) REFERENCES users(P_id)
) ENGINE=InnoDB;

外部キー制約の宣言を黙って無視するのは、MySQL 側の大きな間違いだといつも思っていました。ストレージ エンジンがそれらをサポートしていないというエラーや警告はありません。

同じことが CHECK 制約にも当てはまります。ところで、MySQL で使用されるストレージ エンジンは CHECK 制約をサポートしていませんが、SQL パーサーはそれらを問​​題なく受け入れます。


errno 150 の問題は、外部キー制約を理解できなかったために InnoDB テーブルを作成できない場合に発生します。次の方法でさらに情報を取得できます。

SHOW ENGINE INNODB STATUS;

InnoDB 外部キーの要件:

  • 参照されるテーブルも InnoDB である必要があります。
  • 参照されるテーブルには、インデックスと主キーが必要です。
  • FK 列と参照される PK 列の SQL データ型は同一でなければなりません。たとえば、INT は BIGINT または INT UNSIGNED と一致しません。

データを含むテーブルのストレージ エンジンを変更できます。

ALTER TABLE actions ENGINE=InnoDB;

これにより、MyISAM テーブル全体が InnoDB テーブルに効果的にコピーされ、それが成功すると、MyISAM テーブルが削除され、新しい InnoDB テーブルの名前が以前の MyISAM テーブルの名前に変更されます。これは「テーブルの再構築」と呼ばれ、テーブル内のデータ量によっては時間がかかる場合があります。テーブルの再構築は、不要と思われる場合でも、ALTER TABLE 中に発生します。


あなたのアップデート2について:

機能的な外部キーを使用してデータの整合性を確保することが重要であると言われましたが、MySQL では InnoDB を使用しないでください。おすすめは何ですか?

誰があなたにそれを言ったの?それは絶対に間違っています。 InnoDB は MyISAM よりも優れたパフォーマンスを発揮します (ただし、InnoDBは構成のチューニングに注意を払う必要があります)。InnoDB はアトミックな変更、トランザクション、外部キーをサポートし、InnoDB はクラッシュ時のデータ破損に対する耐性がはるかに優れています。

サポートされていない古いバージョンの MySQL (5.0 以前) を実行している場合を除き、デフォルトのストレージ エンジンの選択肢として InnoDB を使用し、MyISAM の恩恵を受ける特定のワークロードを実証できる場合にのみ MyISAM を使用する必要があります。

于 2008-12-19T04:02:23.723 に答える
9

私が経験した頭痛の時間を節約するために-キリンが触れているように、@ FOREIGN_KEY_CHECKSが1に設定されていることを確認してください.

@@FOREIGN_KEY_CHECKS を選択

SET FOREIGN_KEY_CHECKS=1

于 2011-10-20T22:47:21.113 に答える
6

私はこのスレッドがずっと前に開かれたことを知っていますが、答えを探す将来のユーザーのためにこのメッセージを投稿しています. 私はmysqlの外部キーで同じ問題を抱えていました。次のことは私のために働いた。

親テーブル:

CREATE TABLE NameSubject (
  Autonumber INT NOT NULL AUTO_INCREMENT,
  NameorSubject nvarchar(255),
  PRIMARY KEY (Autonumber)
 ) ENGINE=InnoDB;

子テーブル:

CREATE TABLE Volumes (
  Autonumber INT NOT NULL,
  Volume INT,
  Pages nvarchar(50),
  Reel int,
  Illustrations bit,
  SSMA_TimeStamp timestamp,
  Foreign KEY (Autonumber) references NameSubject(Autonumber)
  ON  update cascade 
)engine=innodb;

「オン更新カスケード」は私にとって魔法でした。

これが他の人にも役立つことを願っています。幸運を祈ります。

于 2010-04-01T15:58:51.177 に答える
1

この問題は、questions.p_id と users.p_id が INT NOT NULL として定義されていない可能性が最も高いです。外部キーが機能するには、auto_increment と default を除いて、外部キーの両側の列の定義が正確に一致する必要があります。

于 2008-12-19T14:59:23.610 に答える
1

この回答を最初に見ていれば、時間を大幅に節約できたでしょう。次の 3 つの手順を試してみてください。初心者の間違いの頻度で並べ替えました。

(1) 「CREATE TABLE」ステートメントに「ENGINE=InnoDB」を追加して、テーブルを InnoDB に変更します。

デフォルトである可能性がある他のエンジンは、外部キー制約をサポートしていませんが、サポートされていないことを知らせるエラーや警告をスローしません。

(2) 「SET foreign_key_checks = 'ON'」を実行して、外部キー制約が実際にチェックされていることを確認します。

(3) 外部キー宣言に「ON UPDATE CASCADE」を追加します。

注: カスケードが目的の動作であることを確認してください。他のオプションがあります...

于 2014-06-01T09:01:20.763 に答える
1

以下の記事を見つけました。現在、テストする時間がありませんが、役立つ場合があります。

http://forums.mysql.com/read.php?22,19755,43805

著者のエドウィン・ダンドは次のように述べています。

両方のテーブルが INNODB である必要があります。外部キー フィールドにはインデックスが必要です。外部キー フィールドと参照されるフィールドは同じ型 (私は整数のみを使用) である必要があり、何時間もの苦労の末、それらは UNSIGNED でなければなりません。

于 2008-12-19T04:20:00.067 に答える
0

前述のように、FK 制約を適用するには、テーブルが InnoDB である必要があります。

ローカル列が外部列とは異なる型である外部キー制約を作成しようとしている場合にのみ、「テーブルを作成できません」に遭遇しました。

于 2008-12-19T04:27:51.220 に答える
0

まあ、私の推測では、どういうわけか「FORIEN KEYS の作成をスキップする」オプションがチェックされており、「フォワード エンジニアリング」プロセスの「オプション」セクションで発生する可能性があります。

フォワード エンジニアリング - オプション セクション

于 2014-09-17T11:25:00.720 に答える
0

この問題を抱えている人の中には、ORACLE Web サイトで提供されている MYSQL 用のサンプル データベース (sakila DB など) から始めている人もいると思います。スクリプトの最後で「外部キー制約をオンに戻す」ことを忘れないでください (たとえば、sakila DB スクリプトの開始時にオフになっています)。

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';

ここにテーブルを作成します

次に、これを忘れないでください:

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
于 2011-09-20T20:50:01.333 に答える