Sposób, w jaki sobie z tym radzę, polega na skonfigurowaniu mojej klasy opakowującej bazę danych, aby zawsze zgłaszała wyjątek, gdy napotkasz błąd bazy danych. Na przykład mogę mieć klasę o nazwie MySQL
z następującymi funkcjami:
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());
}
Za każdym razem, gdy zapytanie kończy się niepowodzeniem, zgłaszany jest zwykły wyjątek PHP. Zwróć uwagę, że wyrzuciłbym je również z innych miejsc, na przykład connect()
funkcja lub selectDb()
funkcji, w zależności od tego, czy operacja się powiodła, czy nie.
Z taką konfiguracją możesz już iść. W każdym miejscu, w którym spodziewasz się, że będziesz musiał obsłużyć błąd bazy danych, wykonaj coś takiego:
//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.
}
}
Edytuj
W odpowiedzi na poniższy komentarz autora masz do dyspozycji pewne ograniczone informacje, które mogą pomóc w zdiagnozowaniu problemu z kluczem obcym. Tekst błędu utworzony przez nieudane ograniczenie klucza obcego i zwrócony przez mysql_error()
wygląda mniej więcej tak:
Cannot delete or update a parent row:
a foreign key constraint fails
(`dbname`.`childtable`, CONSTRAINT `FK_name_1` FOREIGN KEY
(`fieldName`) REFERENCES `parenttable` (`fieldName`));
Jeśli klucze obce są na tyle złożone, że nie masz pewności, co może spowodować błąd klucza obcego dla danego zapytania, prawdopodobnie możesz przeanalizować ten tekst błędu, aby go rozwiązać. Polecenie SHOW ENGINE INNODB STATUS
zwraca również bardziej szczegółowy wynik dla ostatniego błędu klucza obcego.
W przeciwnym razie prawdopodobnie będziesz musiał sam kopać. Następujące zapytanie da ci listę kluczy obcych w danej tabeli, którą możesz sprawdzić pod kątem informacji:
select * from information_schema.table_constraints
WHERE table_schema=schema() AND table_name='table_name';
Niestety, nie wydaje mi się, żeby w twoim rozwiązaniu była jakaś magiczna kula, poza bardzo dokładnym zbadaniem błędów i ograniczeń.