我可以用PHP检测和处理MySQL警告吗?

Can I detect and handle MySQL Warnings with PHP?

提问人:Kyle Noland 提问时间:9/6/2008 最后编辑:Kyle Noland 更新时间:11/14/2019 访问量:17087

问:

我正在处理一个MySQL表,该表将JobName列定义为UNIQUE。如果有人尝试使用数据库中已有的 JobName 将新作业保存到数据库中,MySQL 会抛出警告。

我希望能够在我的PHP脚本中检测到这个警告,就像一个错误一样,并适当地处理它。理想情况下,我想知道MySQL抛出了什么样的警告,以便我可以分支代码来处理它。

这可能吗?如果不是,是因为MySQL没有这个能力,PHP没有这个能力,还是两者兼而有之?

PHP MySQL 错误处理 警告

评论


答:

4赞 Kyle Cronin 9/7/2008 #1

首先,您应该关闭警告,以便访问者不会看到您的 MySQL 错误。其次,当你调用 mysql_query() 时,你应该检查它是否返回 false。如果是这样,请调用 mysql_errno() 以找出问题所在。将返回的数字与此页上的错误代码相匹配。

看起来这是您要查找的错误号:

错误: 1169 SQLSTATE: 23000 (ER_DUP_UNIQUE)

消息:由于唯一约束,无法写入表 '%s'

评论

9赞 Andrew 12/8/2013
如果我没记错的话,他问的是警告,而不是错误。警告仍允许查询通过,因此不会返回 。请参阅 iAn 的答案,了解 PHP 的有限警告支持。mysql_queryfalse
0赞 yukondude 9/7/2008 #2

更新以删除有关errno函数的内容,我现在意识到这些内容不适用于您的情况...

MySQL中需要注意的一件事是:即使子句与行匹配,也会返回零,但该子句实际上并没有更改数据值。我之所以提到这一点,是因为这种行为在我曾经看过的系统中导致了一个错误——程序员在更新后使用该返回值来检查错误,假设零意味着发生了一些错误。这只是意味着用户在单击更新按钮之前没有更改任何现有值。UPDATEmysqli_affected_rows()WHERESET

所以我想也不能依靠使用来找到这样的警告,除非你的表中有类似列的东西,在更新时总是会被分配一个新的时间戳值。不过,这种解决方法似乎有点笨拙。mysqli_affected_rows()update_time

0赞 Alexander Morland 9/7/2008 #3

根据您使用的框架(如果有),我建议您自己进行查询以检查作业名称,并为用户创建适当的信息以及表单的其余验证。

根据作业名称的数量,您可以将名称发送到包含表单的视图,并使用 javascript 来告知使用哪个。

如果这对你来说没有意义,那么总结我的观点是这样的:不要设计你的程序和/或用户试图做非法的事情,并在他们这样做时发现错误并处理它。恕我直言,最好将系统设计为不会产生错误。将错误保留为实际的 bug :)

13赞 Ian 9/7/2008 #4

要将警告“标记”到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

评论

0赞 Bob Fanger 10/19/2011
或者使用具有 warning_count 属性的 MySQLi 驱动程序。php.net/manual/en/mysqli.warning-count.php
0赞 Sanjeev Jha 5/30/2009 #5

您可以使用 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);
        }
0赞 tomsv 1/9/2010 #6

使用 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();
    }
}
0赞 AG3 2/21/2011 #7

禁止显示警告的注意事项:通常,阻止显示警告不是一个好主意,因为您可能会遗漏一些重要内容。如果您出于某种原因绝对必须隐藏警告,您可以通过在声明前面放置一个标志来单独隐藏。这样,您就不必关闭所有警告报告,并且可以将其限制为特定实例。@

例:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");

评论

4赞 pgreen2 11/29/2012
听起来用户希望能够捕获错误,而不是压制它。
0赞 Chinoto Vokro 7/12/2014
这是一个更好的主意(更好的是,把它放在你的php.ini中),这样用户就不会看到任何可能带来安全风险的东西。除此之外,我建议确保将其设置为可写文件并进行设置,以便知道每个潜在问题。ini_set('display_errors',0);error_logerror_reporting = -1
3赞 Gigi 11/7/2011 #8
ini_set('mysql.trace_mode', 1)

可能就是你要找的。

然后可以使用自定义PHP错误处理程序处理PHP错误,但您也可以关闭显示php错误,因为它们通常记录到日志文件中(取决于您的php配置)。