Верный способ составить список внешних ключей для таблицы MySQL? - PullRequest
4 голосов
/ 17 сентября 2011

Есть ли исполнитель способ получения списка внешних ключей, назначенных таблице 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, с которыми я пробовал. Небольшое исследование обнаружило эту ошибку , которая, кажется, указывает на то, что это постоянная проблема без ясного решения. Решения, на которые намекают, требуют переконфигурирования или перекомпиляции mysql с патчем, который не работает для проекта, над которым я работаю.

Я понимаю, что возможно выдать следующее

SHOW CREATE TABLE table_name;

и получите строковое представление инструкции CREATE TABLE, которая будет включать ограничения внешнего ключа. Тем не менее, синтаксический анализ этой строки кажется хрупким, и у меня нет большого набора операторов CREATE TABLE для проверки. (если есть стандартный код разбора для этого, я бы хотел несколько ссылок)

Я также понимаю, что могу перечислить индексы со следующим

SHOW CREATE TABLE table_name;

Список индексов будет включать внешние ключи, но, похоже, нет способа определить, какие из индексов являются внешними ключами, а какие - "обычными" индексами MySQL. Опять же, здесь могут помочь некоторые перекрестные ссылки с информацией таблицы SHOW CREATE, но это возвращает нас к хрупкому разбору строк.

Буду признателен за любую помощь или даже ссылки на другие умные дискуссии по этому вопросу.

1 Ответ

3 голосов
/ 17 сентября 2011

SequelPro и Magento используют запрос SHOW CREATE TABLE для загрузки информации о внешнем ключе.Реализация Magento - это та, на которую я собираюсь сослаться, поскольку это и система на основе PHP, и та, с которой мы оба хорошо знакомы.Однако следующие фрагменты кода могут быть применены к любой системе, основанной на PHP.

Разбор выполняется методом Varien_Db_Adapter_Pdo_Mysql::getForeignKeys() ( код для этого класса можно найти здесь ) с помощьюОтносительно простой RegEx:


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

В блоке документации он описывает результирующий массив следующим образом:


    /**
     * 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, но, основываясь на моих выводах, он, похоже, является общепринятым способом ведения дел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...