2011-09-16 8 views
4

performant MySQLテーブルに割り当てられた外部キーのリストを取得する方法はありますか?MySQLテーブルの外部キーをリストする実行方法

SELECT 
    `column_name`, 
    `referenced_table_schema` AS foreign_db, 
    `referenced_table_name` AS foreign_table, 
    `referenced_column_name` AS foreign_column 
FROM 
    `information_schema`.`KEY_COLUMN_USAGE` 
WHERE 
    `constraint_schema` = SCHEMA() 
AND 
    `table_name` = 'your-table-name-here' 
AND 
    `referenced_column_name` IS NOT NULL 
ORDER BY 
    `column_name`; 

作品との情報スキーマの照会、しかし、私はそれを試してみたのMySQLのバージョンで痛々しいほど遅いです。研究の一部がthis bugとなっています。これは明らかな解決策がないまま進行中の問題であることを示しているようです。私が取り組んでいるプロジェクトではうまくいかないパッチでmysqlを再構成または再コンパイルする必要があります。

私はそれは、次の

SHOW CREATE TABLE table_name; 

を発行し、外部キー制約が含まれますCREATE TABLE文の文字列表現を取得することが可能です実現。しかし、この文字列を解析するのは壊れやすいようですが、テストするCREATE TABLE文のコーパスが大量にありません。

を(が、このためのコードを解析する標準ビットがありますならば、私はいくつかのリンクをみたい)私も、私は、インデックスのリストが含まれます、次の

SHOW CREATE TABLE table_name; 

でインデックスを一覧表示することができます実現外部キーであるが、どちらのインデックスが外部キーであり、どれが「通常の」MySQLインデックスであるかを判断する方法はないようである。ここでも、SHOW CREATEテーブル情報を使ったいくつかの相互参照が役に立ちましたが、それは壊れやすい文字列解析に戻ってしまいます。

この問題に関するその他のスマートな議論への助けや、他のスマートな議論へのリンクさえも高く評価されます。

+0

私は、テーブルの外部キー部分のための簡単なパーサーを書くのが壊れやすい理由はわかりません... create tableの構文はmysqlのドキュメントで明確に定義されています... – Zak

+0

私はなぜパフォーマンスが良いのですか?このようなクエリでは問題になります。データベース構造を1秒間に50回調べるのではなく、そうした場合、アプリケーションにひどい問題があります。 – GolezTrol

+0

@Zakそれは哲学的なことですが、私はそれが最終的に私がする必要があると考えています。私は、ドキュメントでカバーされていないエッジケースには気をつけています。私は、SHOW CREATE TABLE構文が有効な構文ではないものを返すかもしれないmysqlバージョンを気にしています。最初。 –

答えて

3

SequelProとMagentoは両方とも、SHOW CREATE TABLEクエリを使用して外部キー情報をロードします。 Magentoの実装は、PHPベースのシステムと私たちの両方が非常に精通しているシステムなので、私が参照しようとしているものです。ただし、次のコードスニペットはPHPベースのシステムに適用できます。私はそれを知っている


    /** 
    * The return value is an associative array keyed by the UPPERCASE foreign key, 
    * as returned by the RDBMS. 
    * 
    * The value of each array element is an associative array 
    * with the following keys: 
    * 
    * FK_NAME   => string; original foreign key name 
    * SCHEMA_NAME  => string; name of database or schema 
    * TABLE_NAME  => string; 
    * COLUMN_NAME  => string; column name 
    * REF_SCHEMA_NAME => string; name of reference database or schema 
    * REF_TABLE_NAME => string; reference table name 
    * REF_COLUMN_NAME => string; reference column name 
    * ON_DELETE  => string; action type on delete row 
    * ON_UPDATE  => string; action type on update row 
    */ 

:次のように得られた配列を記述するドキュメントブロック内


    $createSql = $this->getCreateTable($tableName, $schemaName); 

    // collect CONSTRAINT 
    $regExp = '#,\s+CONSTRAINT `([^`]*)` FOREIGN KEY \(`([^`]*)`\) ' 
     . 'REFERENCES (`[^`]*\.)?`([^`]*)` \(`([^`]*)`\)' 
     . '(ON DELETE (RESTRICT|CASCADE|SET NULL|NO ACTION))?' 
     . '(ON UPDATE (RESTRICT|CASCADE|SET NULL|NO ACTION))?#'; 
    $matches = array(); 
    preg_match_all($regExp, $createSql, $matches, PREG_SET_ORDER); 
    foreach ($matches as $match) { 
     $ddl[strtoupper($match[1])] = array(
      'FK_NAME'   => $match[1], 
      'SCHEMA_NAME'  => $schemaName, 
      'TABLE_NAME'  => $tableName, 
      'COLUMN_NAME'  => $match[2], 
      'REF_SHEMA_NAME' => isset($match[3]) ? $match[3] : $schemaName, 
      'REF_TABLE_NAME' => $match[4], 
      'REF_COLUMN_NAME' => $match[5], 
      'ON_DELETE'   => isset($match[6]) ? $match[7] : '', 
      'ON_UPDATE'   => isset($match[8]) ? $match[9] : '' 
     ); 
    } 

解析は比較的簡単な正規表現を使用してVarien_Db_Adapter_Pdo_Mysql::getForeignKeys()方法(the code for this class can be found here)で行われます正確には SHOW CREATE TABLEの出力を使用しているので、あなたが求めていたものですが、私の発見に基づいて、これは一般的に受け入れられている方法です。

関連する問題