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アクション;」コマンドを使用すると、外部キーがMULタイプのキーであることがわかり、これが何を意味するのかわかりません)。ただし、質問テーブルまたはユーザーテーブルに存在しないQ_idまたはU_idを入力しようとすると、MySQLではこれらの値が引き続き許可されます。
私は何を間違えましたか?外部キーを持つテーブルが無効なデータを受け入れないようにするにはどうすればよいですか?
最後にTYPE=InnoDB
を追加すると、エラーが発生します。
エラー1005(HY000):テーブル './quotes/actions.frm'を作成できません(エラー番号:150)
なぜそれが起こるのでしょうか?
機能的な外部キーを使用してデータの整合性を強化することが重要であると言われていますが、MySQLではInnoDBを使用しないでください。何がお勧めですか?
デフォルトのストレージエンジンは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外部キーのいくつかの要件:
データを含むテーブルのストレージエンジンを変更できます。
ALTER TABLE actions ENGINE=InnoDB;
これにより、MyISAMテーブル全体がInnoDBテーブルに効果的にコピーされ、成功するとMyISAMテーブルが削除され、新しいInnoDBテーブルの名前が以前のMyISAMテーブルの名前に変更されます。これは「テーブルの再構築」と呼ばれ、テーブル内のデータ量によっては時間がかかる場合があります。テーブルの再構築は、不要と思われる場合でも、ALTERTABLE中に発生します。
アップデート2について:
機能的な外部キーを使用してデータの整合性を強化することが重要であると言われていますが、MySQLではInnoDBを使用しないでください。何がお勧めですか?
誰があなたにそれを言ったの?それは絶対に間違っています。 InnoDBのパフォーマンスはMyISAMよりも優れています (ただし、InnoDBはより注意を払う必要があります 構成の調整 )、InnoDBはアトミックな変更、トランザクション、外部キーをサポートし、InnoDBは破損に対してはるかに耐性がありますクラッシュしたデータ。
サポートされていない古いバージョンのMySQL(5.0以前)を実行している場合を除き、defaultストレージエンジンの選択肢としてInnoDBを使用し、MyISAMのみを使用する必要がありますMyISAMの恩恵を受ける特定のワークロードを示すことができるかどうか。
私が経験した他の頭痛の時間を節約するために、giraffaが触れているように、@ FOREIGN_KEY_CHECKSが1に設定されていることを確認してください。
SELECT @@ FOREIGN_KEY_CHECKS
SET FOREIGN_KEY_CHECKS = 1
このスレッドはずっと前に開かれたことを知っていますが、答えを探す将来のユーザーのためにこのメッセージを投稿しています。私は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;
「ONupdatecascade」は私にとって魔法のようでした。
これが他の人にも役立つことを願っています。幸運を祈ります。
問題は、questions.p_idとusers.p_idがINT NOTNULLとして定義されていない可能性が高いです。外部キーが機能するには、auto_incrementとdefaultを除いて、外部キーの両側の列の定義が正確に一致している必要があります。
私が最初にそれを見たならば、この答えは私に多くの時間を節約したでしょう。初心者のミスの頻度で注文した次の3つの手順を試してください。
(1)「CREATETABLE」ステートメントに「ENGINE = InnoDB」を追加して、テーブルをInnodDBに変更します。
デフォルトである可能性のある他のエンジンは、外部キー制約をサポートしていませんが、サポートされていないことを通知するエラーや警告をスローすることもありません。
(2)「SETforeign_key_checks = 'ON'」を実行して、外部キー制約が実際にチェックされていることを確認します。
(3)外部キー宣言に「ONUPDATECASCADE」を追加します。
注:カスケードが目的の動作であることを確認してください。他のオプションがあります...
次の記事を見つけました。現在、テストする時間がありませんが、役立つ場合があります。
http://forums.mysql.com/read.php?22,19755,43805
著者のエドウィン・ダンドは次のように述べています。
両方のテーブルがINNODBである必要があります。外部キーフィールドにはインデックスが必要です。敵のキーフィールドと参照されるフィールドは同じタイプである必要があり(私は整数のみを使用します)、何時間もの苦痛の後、それらは署名されていない必要があります。
この問題を抱えている人の中には、MySQL用のOracle Webサイトで提供されているサンプルデータベース(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;
Mysqlが外部キーの制約を無視することにまだ問題がある人、および上記の回答やその他の関連する質問でteirパズルを解決できなかった人のために、これが問題であることがわかりました。
外部キーをそのように宣言した場合
id INTEGER UNSIGNED REFERENCES A_Table(id)
次に、外部キーは無視されているようです。SETコマンドを使用せずに(明らかに)制約を適用するには、次の宣言を使用します。
id INTEGER UNSIGNED,
CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES A_Table(id)
このようにして私は問題を解決しました。多くの人が言うように、最初の宣言は2番目のバリアントの省略形にすぎないと言う理由はわかりません。
前述のように、FK制約を適用するには、テーブルがInnoDBである必要があります。
ローカル列が外部列とは異なるタイプである外部キー制約を作成しようとしている場合にのみ、「テーブルを作成できません」に遭遇しました。
さて、私の推測では、「FOREIGN KEYSの作成をスキップする」オプションがチェックされています。これは、「ForwardEngineering」プロセスの「options」セクションで発生する可能性があります。