提问人:Kyle Noland 提问时间:9/6/2008 最后编辑:Kyle Noland 更新时间:11/14/2019 访问量:17087
我可以用PHP检测和处理MySQL警告吗?
Can I detect and handle MySQL Warnings with PHP?
问:
我正在处理一个MySQL表,该表将JobName列定义为UNIQUE。如果有人尝试使用数据库中已有的 JobName 将新作业保存到数据库中,MySQL 会抛出警告。
我希望能够在我的PHP脚本中检测到这个警告,就像一个错误一样,并适当地处理它。理想情况下,我想知道MySQL抛出了什么样的警告,以便我可以分支代码来处理它。
这可能吗?如果不是,是因为MySQL没有这个能力,PHP没有这个能力,还是两者兼而有之?
答:
首先,您应该关闭警告,以便访问者不会看到您的 MySQL 错误。其次,当你调用 mysql_query()
时,你应该检查它是否返回 false。如果是这样,请调用 mysql_errno()
以找出问题所在。将返回的数字与此页上的错误代码相匹配。
看起来这是您要查找的错误号:
错误: 1169 SQLSTATE: 23000 (ER_DUP_UNIQUE)
消息:由于唯一约束,无法写入表 '%s'
评论
mysql_query
false
更新以删除有关errno函数的内容,我现在意识到这些内容不适用于您的情况...
MySQL中需要注意的一件事是:即使子句与行匹配,也会返回零,但该子句实际上并没有更改数据值。我之所以提到这一点,是因为这种行为在我曾经看过的系统中导致了一个错误——程序员在更新后使用该返回值来检查错误,假设零意味着发生了一些错误。这只是意味着用户在单击更新按钮之前没有更改任何现有值。UPDATE
mysqli_affected_rows()
WHERE
SET
所以我想也不能依靠使用来找到这样的警告,除非你的表中有类似列的东西,在更新时总是会被分配一个新的时间戳值。不过,这种解决方法似乎有点笨拙。mysqli_affected_rows()
update_time
根据您使用的框架(如果有),我建议您自己进行查询以检查作业名称,并为用户创建适当的信息以及表单的其余验证。
根据作业名称的数量,您可以将名称发送到包含表单的视图,并使用 javascript 来告知使用哪个。
如果这对你来说没有意义,那么总结我的观点是这样的:不要设计你的程序和/或用户试图做非法的事情,并在他们这样做时发现错误并处理它。恕我直言,最好将系统设计为不会产生错误。将错误保留为实际的 bug :)
要将警告“标记”到PHP中,需要对mysql / mysqli驱动程序进行更改,这显然超出了这个问题的范围。相反,你基本上必须检查你对数据库所做的每个查询是否有警告:
$warningCountResult = mysql_query("SELECT @@warning_count");
if ($warningCountResult) {
$warningCount = mysql_fetch_row($warningCountResult );
if ($warningCount[0] > 0) {
//Have warnings
$warningDetailResult = mysql_query("SHOW WARNINGS");
if ($warningDetailResult ) {
while ($warning = mysql_fetch_assoc($warningDetailResult) {
//Process it
}
}
}//Else no warnings
}
显然,大规模应用这将是非常昂贵的,所以你可能需要仔细考虑何时以及如何出现警告(这可能会导致你重构以消除它们)。
作为参考,MySQL SHOW WARNINGS
当然,您可以省去对 的初始查询,这将为您节省每次执行的查询,但我将其包含在内是为了迂腐的完整性。SELECT @@warning_count
评论
您可以使用 mysqli 语句错误 no 来检测唯一键冲突。mysqli语句返回错误 1062 ,即ER_DUP_ENTRY。您可以查找错误 1062 并打印合适的错误消息。如果要将列 (jobName) 也打印为错误消息的一部分,则应解析语句错误字符串。
if($stmt = $mysqli->prepare($sql)){ $stmt->bind_param("sss", $name, $identKey, $domain); $stmt->execute(); if($mysqli->affected_rows != 1) { //This will return errorno 1062 trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR); exit(1); } $stmt->close(); } else { trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR); }
使用 mysqli 可以比使用 mysqli 更有效的方式获取警告。
以下是 mysqli->warning_count 属性的 php.net 手册页上建议的代码:
$mysqli->query($query);
if ($mysqli->warning_count) {
if ($result = $mysqli->query("SHOW WARNINGS")) {
$row = $result->fetch_row();
printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
$result->close();
}
}
禁止显示警告的注意事项:通常,阻止显示警告不是一个好主意,因为您可能会遗漏一些重要内容。如果您出于某种原因绝对必须隐藏警告,您可以通过在声明前面放置一个标志来单独隐藏。这样,您就不必关闭所有警告报告,并且可以将其限制为特定实例。@
例:
// this suppresses warnings that might result if there is no field titled "field" in the result
$field_value = @mysql_result($result, 0, "field");
评论
ini_set('display_errors',0);
error_log
error_reporting = -1
ini_set('mysql.trace_mode', 1)
可能就是你要找的。
然后可以使用自定义PHP错误处理程序处理PHP错误,但您也可以关闭显示php错误,因为它们通常记录到日志文件中(取决于您的php配置)。
评论