Způsob, jakým to řeším, je nastavit třídu obálky databáze tak, aby vždy vyvolala výjimku, když narazíte na chybu databáze. Takže bych například mohl mít třídu s názvem MySQL
s následujícími funkcemi:
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());
}
Kdykoli dotaz selže, je vyvolána běžná výjimka PHP. Všimněte si, že bych je hodil i z jiných míst, jako je connect()
funkce nebo selectDb()
v závislosti na tom, zda operace proběhla úspěšně nebo ne.
S tímto nastavením můžete začít. Na jakémkoli místě, kde očekáváte, že budete muset řešit chybu databáze, proveďte něco takového:
//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.
}
}
Upravit
V reakci na níže uvedený komentář plakátu máte k dispozici některé omezené informace, které vám pomohou diagnostikovat problém s cizím klíčem. Text chyby vytvořený neúspěšným omezením cizího klíče a vrácený funkcí mysql_error()
vypadá asi takto:
Cannot delete or update a parent row:
a foreign key constraint fails
(`dbname`.`childtable`, CONSTRAINT `FK_name_1` FOREIGN KEY
(`fieldName`) REFERENCES `parenttable` (`fieldName`));
Pokud jsou vaše cizí klíče natolik složité, že si nemůžete být jisti, co by mohlo způsobit chybu cizího klíče pro daný dotaz, pravděpodobně byste mohli tento chybový text analyzovat, abyste na to přišli. Příkaz SHOW ENGINE INNODB STATUS
vrátí podrobnější výsledek také pro nejnovější chybu cizího klíče.
V opačném případě budete pravděpodobně muset kopat sami. Následující dotaz vám poskytne seznam cizích klíčů v dané tabulce, které můžete prozkoumat:
select * from information_schema.table_constraints
WHERE table_schema=schema() AND table_name='table_name';
Bohužel si nemyslím, že by vaše řešení mělo nějaký zázračný nástroj, než velmi pečlivé prozkoumání chyb a omezení.