在PHP中处理外键异常

在PHP中处理外键异常,php,mysql,foreign-keys,Php,Mysql,Foreign Keys,PHP中处理mysql数据库上的外键异常的最佳方法是什么?是否有一个mysql类可以用来简化任何代码 理想情况下,作为一个示例,我想做的是尝试删除一条记录,其中该记录是任意多个子表的外键父项。外键抛出异常,因此我希望能够查看每个外键表并对其进行测试,对导致异常的表和记录数给出有意义的反馈。然后,这将作为错误返回,以便最终用户可以引用和删除有问题的记录。我认为最好的办法是让您执行一个操作。这样,插入将始终有效,或者根本不执行。这可能会返回一条错误消息,您也可以处理它。这将避免您必须手动检查每个表—

PHP中处理mysql数据库上的外键异常的最佳方法是什么?是否有一个mysql类可以用来简化任何代码


理想情况下,作为一个示例,我想做的是尝试删除一条记录,其中该记录是任意多个子表的外键父项。外键抛出异常,因此我希望能够查看每个外键表并对其进行测试,对导致异常的表和记录数给出有意义的反馈。然后,这将作为错误返回,以便最终用户可以引用和删除有问题的记录。

我认为最好的办法是让您执行一个操作。这样,插入将始终有效,或者根本不执行。这可能会返回一条错误消息,您也可以处理它。这将避免您必须手动检查每个表—db会为您执行此操作。

我处理此问题的方法是将我的数据库包装类设置为在遇到数据库错误时始终引发异常。例如,我可能有一个名为
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\u 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';

不幸的是,我认为除了非常仔细地检查错误和约束之外,您的解决方案没有什么灵丹妙药。

谢谢您的回复,但据我所知,事务只打包了查询。我想做的是,在异常触发后,对导致异常的实际子记录提供有意义的反馈。这看起来是从结构上控制错误处理的好方法,但我真的想知道是否可以动态列出子表,然后查询这些子表以列出实际的异常。因此,这就是我一直在努力解决的“做点事情”的内在原因。:)这几乎与我自己的方法相同。