Обработка исключений внешнего ключа в PHP - PullRequest
6 голосов
/ 16 ноября 2009

Каков наилучший способ в PHP для обработки исключений внешнего ключа в базе данных mysql? Есть ли класс mysql, который можно использовать для упрощения любого кода?

В идеале в качестве примера я хочу попытаться удалить запись, в которой она является родителем внешнего ключа, для любого количества дочерних таблиц. Внешний ключ выдает исключение, поэтому я хотел бы иметь возможность просмотреть каждую таблицу внешнего ключа и протестировать ее, предоставив значимые отзывы о таблицах и количестве записей, вызвавших исключение. Затем это будет возвращено как ошибка, чтобы конечный пользователь мог ссылаться и удалять ошибочные записи.

Ответы [ 2 ]

6 голосов
/ 16 ноября 2009

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

public function query($query_string)
{
    $this->queryId = mysql_query($query_string,$this->connectionId);
    if (! $this->queryId) {
        $this->_throwException($query_string);
    }
    return $this->queryId;
}

private function _throwException($query = null)
{
    $msg = mysql_error().".  Query was:\n\n".$query.
                "\n\nError number: ".mysql_errno();
    throw new Exception($msg,mysql_errno());
}

Каждый раз, когда запрос не выполняется, выдается обычное исключение PHP. Обратите внимание, что я бы выбрасывал их и из других мест, например, функции connect() или selectDb(), в зависимости от того, была ли операция успешной или нет.

С этой настройкой ты в порядке. В любом месте, где вы ожидаете обработки ошибки базы данных, сделайте что-то вроде следующего:

//assume $db has been set up to be an instance of the MySQL class

try {
    $db->query("DELETE FROM parent WHERE id=123");
} catch (Exception $e) {
    //uh-oh, maybe a foreign key restraint failed?
    if ($e->getCode() == 'mysql foreign key error code') {
        //yep, it failed.  Do some stuff.
    }
}

Редактировать

В ответ на комментарий автора ниже, у вас есть ограниченная информация, доступная для диагностики проблемы с внешним ключом. Текст ошибки, созданный ошибкой ограничения внешнего ключа и возвращенный mysql_error(), выглядит примерно так:

Cannot delete or update a parent row:
a foreign key constraint fails
(`dbname`.`childtable`, CONSTRAINT `FK_name_1` FOREIGN KEY
(`fieldName`) REFERENCES `parenttable` (`fieldName`));

Если ваши внешние ключи достаточно сложны, и вы не можете быть уверены, что может вызвать ошибку внешнего ключа для данного запроса, то вы, вероятно, можете проанализировать этот текст ошибки, чтобы помочь выяснить это. Команда SHOW ENGINE INNODB STATUS возвращает более подробный результат и для последней ошибки внешнего ключа.

В противном случае вам, вероятно, придется самому покопаться. Следующий запрос даст вам список внешних ключей для данной таблицы, который вы можете проверить для информации:

select * from information_schema.table_constraints
WHERE table_schema=schema() AND table_name='table_name';

К сожалению, я не думаю, что у вашего решения есть волшебная палочка, кроме тщательного изучения ошибок и ограничений.

0 голосов
/ 16 ноября 2009

Я думаю, что лучше всего было бы совершить транзакцию .Таким образом, вставка всегда будет действительной или не будет сделана вообще.Это может вернуть сообщение об ошибке, с которым вы также можете работать.Это избавит вас от необходимости вручную проверять каждую таблицу - БД сделает это за вас.

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