sql >> データベース >  >> RDS >> Mysql

ER_FK_NO_INDEX_PARENT:外部キー制約の追加に失敗しました。制約のインデックスがありません

    まず、スキーマを分析して理解してみてください。理由がわかりません。なぜteamname 主キーの一部である必要があります。 ID AUTO_INCREMENT により、列はすでに一意です オプション。したがって、主キーにすることができます。

    次に、 teamnameの制約を分析します 。 2つのチームが同じ名前を持つことができない場合は、 UNIQUE KEYを定義する必要があります teamnameの制約 。すべてのチームに名前が必要な場合は、 NOT NULLを定義する必要があります teamnameの制約 。これらの制約がある場合、 team 次のように作成できます:

    CREATE TABLE IF NOT EXISTS teams (
      ID INT NOT NULL AUTO_INCREMENT,
      teamname VARCHAR(255) NOT NULL,
      PRIMARY KEY (ID),
      UNIQUE KEY (teamname )
    );
    

    これで、 teamnameを使用できます teamの行を識別する列 テーブル、および他のテーブルの外部キーとして使用できます。 プレーヤーのコード これでテーブルが機能するはずです(デモ を参照) 。

    通常、外部キーは別のテーブルの主キーを参照することに注意してください。 プレーヤー テーブルは次のように定義されます:

    CREATE TABLE IF NOT EXISTS players (
      ID INT NOT NULL AUTO_INCREMENT,
      player_name VARCHAR(255),
      cm INT NOT NULL,
      team_id INT,
      PRIMARY KEY (ID),
      FOREIGN KEY (team_id) REFERENCES teams(ID)
    );
    

    プレーヤーのチーム名を知る必要がある場合は、JOINを使用します:

    SELECT p.*, t.teamname
    FROM players p
    LEFT JOIN teams t on t.ID = p.team_id
    

    注:ここ数日、同じパターンの質問を何度も見ました。パターンは次のとおりです。他のテーブルの主キーの一部を参照する外部キー。いくつかの例:

    FK制約チェックをサポートするために、参照されるテーブルに単純なインデックスを定義するためのコメントと回答が提案されました。 そうしないでください! teamnameにインデックスを定義するだけで問題を解決しようとするかどうかを検討してください。 チーム テーブル:

    CREATE TABLE IF NOT EXISTS teams (
      ID INT NOT NULL AUTO_INCREMENT,
      teamname VARCHAR(255) NOT NULL,
      PRIMARY KEY (ID),
      INDEX (teamname )
    );
    

    MySQLはそれを受け入れます(デモ を参照) )。ただし、スキーマでは、同じ名前の2つのチームが許可されています。 「サル」という名前のチームが2つあるとします。そして、チーム名(FK)として「サル」を持っているプレーヤーがいます。 2つのチームのどちらが参照されますか?言えない!したがって、単純なルールに固執する方がよいでしょう。また、外部キーのルールは次のとおりです。完全なUNIQUEまたはPRIMARYKEYのみを参照します。またはさらに簡単:完全な主キーのみを参照します。外部キー値は、参照されるテーブルの特定の行を識別する必要があります。




    1. MySQLはALTERTABLEクエリに対して非常に遅い

    2. データの削除/ロードスクリプトを実行する前に、Oracleデータベースをロックします

    3. 集計関数COUNTを使用してレコードをフィルタリングする方法

    4. サーバーからの応答を保存する方法、およびそのデータにアクセスするにはどうすればよいですか