2011-09-16 45 views
4

是否有高性能獲取分配給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

我不明白爲什麼寫一個簡單的解析器爲創建表的外鍵部分會很脆弱...創建表語法在mysql文檔中明確定義... – Zak

+0

我很好奇爲什麼性能在這樣的查詢中很重要。這並不是說你想每秒調查一次數據庫結構50次,如果你這樣做,那麼你的應用程序出現了一些可怕的錯誤。 – GolezTrol

+0

@Zak這是一個哲學的東西,但我懷疑這最終是我需要做的。我對文檔中沒有涉及的邊緣情況保持警惕,我對使用SHOW CREATE TABLE語法的mysql版本保持警惕,可能會返回一些無效的語法,而且我無法克服這種謹慎,第一。 –

回答

3

SequelPro和Magento都使用SHOW CREATE TABLE查詢來加載外鍵信息。 Magento的實現是我將要參考的,因爲它既是一個基於PHP的系統,也是我們兩個都非常熟悉的系統。但是,以下代碼片段可以應用於任何基於PHP的系統。

解析是利用一個相對簡單的正則表達式中的Varien_Db_Adapter_Pdo_Mysql::getForeignKeys()方法(the code for this class can be found here)完成:


    $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] : '' 
     ); 
    } 

在DOC塊它描述所得陣列如下:


    /** 
    * 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 
    */ 

我知道它的不是正好是你所要求的,因爲它使用SHOW CREATE TABLE輸出,但是根據我的發現,它似乎是普遍接受的做事方式。