Intereting Posts
php client отправляет двоичные данные в CakePHP 500 – Произошла ошибка! Функция DB сообщает об ошибках при добавлении новой статьи в Joomla! Обрезаемая фатальная ошибка: объект класса stdClass не может быть преобразован в строку в … после попытки вставить в базу данных Рекомендации по локализации PHP? GetText? nginx переписать в php-файл – Файл загружается PHP – Сортировка многомерного массива другим массивом Класс Autoload с соглашением об именах на основе Zend или вообще не согласуется с Symfony 2 Переопределение PHP.ini в общей среде разработки PHP GD Jpeg с целевым размером файла php: сохранить всю переменную $ _POST в сеансе Codeigniter: невозможно подключиться к серверу базы данных, используя предоставленные настройки Преобразование плоского массива в многомерное PHP Startup: невозможно загрузить динамическую библиотеку 'C: \ Program Files (x86) \ PHP \ v5.6 \ ext \ php_sqlsrv_55_ts.dll Как создать чат Gmail? Как подключиться к AIM и разрешить чат AIM? Функция PHP для извлечения значения поля из базы данных

Обработка исключений внешних ключей в PHP

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

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

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

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

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