Способ, которым я справляюсь с этим, состоит в том, чтобы настроить мой класс-оболочку базы данных так, чтобы он всегда выдавал исключение при возникновении ошибки базы данных. Так, например, у меня может быть класс с именем 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';
К сожалению, я не думаю, что у вашего решения есть волшебная палочка, кроме тщательного изучения ошибок и ограничений.