26

ここ数週間、SQLをゆっくりと学んでいます。私はすべての関係代数とリレーショナルデータベースがどのように機能するかの基本を学びました。私が今やろうとしているのは、それがどのように実装されているかを学ぶことです。

私がこれで遭遇したつまずきは、MySQLの外部キーです。MySQLが持っているInnoDBストレージスキーマに存在すること以外は、あまり見つけられないようです。

MySQLに実装された外部キーの簡単な例は何ですか?

これが私が書いたスキーマの一部であり、実際の例を示すよりも私の欠陥を指摘したい場合は機能していないようです。

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories,
Foreign Key(`uID`) references users
) ENGINE=InnoDB;
4

5 に答える 5

26

カテゴリとユーザー テーブルが既に存在し、それぞれ主キーとして cID と uID が含まれていると仮定すると、これは機能するはずです。

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories(`cID`),
Foreign Key(`uID`) references users(`uID`)
) ENGINE=InnoDB;

references句には列名が必要です。

于 2008-10-25T16:57:43.937 に答える
10

編集: Robert と Vinko は、外部キー制約で参照される列の名前を宣言する必要があると述べています。これは InnoDB で必要ですが、標準 SQL では、参照先の列名が親テーブルと同じ名前である場合、その列名を省略できます。

MySQL で私が遭遇した 1 つの特異性は、外部キーの宣言がいくつかの状況でサイレントに失敗することです。

  • MySQL インストールに innodb エンジンが含まれていない
  • MySQL 構成ファイルで innodb エンジンが有効になっていません
  • ENGINE=InnoDB テーブル修飾子を使用してテーブルを宣言しない
  • 外部キー列が、参照先テーブルの主キー列と正確に同じデータ型ではありません

残念ながら、MySQL は外部キー制約の作成に失敗したというメッセージを表示しません。単にリクエストを無視し、外部キーなしでテーブルを作成します (SHOW CREATE TABLE ポストを行うと、外部キー宣言が表示されない場合があります)。これは MySQL の悪い機能だといつも思っていました。

ヒント:整数データ型 (BIGINT(20) など) の整数引数は必要ありません。列のストレージ サイズや範囲とは関係ありません。BIGINT は、指定した引数に関係なく、常に同じサイズです。この数値は、ZEROFILL 列修飾子を使用した場合に MySQL が列を埋める桁数を示します。

于 2008-10-25T17:50:44.797 に答える
5

これには、外部キーを単独で、および CREATE TABLE で作成する方法を示すコードが含まれています。

以下は、その簡単な例の 1 つです。

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id INT, 
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent(id)
    ON DELETE CASCADE
) ENGINE=INNODB;
于 2008-10-25T16:50:22.940 に答える
4

私はロバートに同意します。参照句に列の名前がありません (エラー 150 が発生するはずです)。テーブルが実際にどのように作成されたかを確認できることを追加します。

SHOW CREATE TABLE posts;
于 2008-10-25T17:01:36.597 に答える
2

前の回答は、外部キー制約を扱っています。外部キー制約は参照整合性を維持するのに非常に役立ちますが、制約を使用するかどうかに関係なく、「外部キー」の概念自体がデータのリレーショナル モデルの基本となります。

equijoinを実行するときはいつでも、外部キーを何か (通常はそれが参照するキー) と同一視しています。例:

select *
from 
   Students
inner join
   StudentCourses
on Students.StudentId = StudentCourses.StudentId

StudentCourses.StudentId は、Students.StudentId を参照する外部キーです。

于 2008-10-25T19:48:49.303 に答える