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

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

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

有帮助吗?

解决方案

对于本地“标记”到 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 显示警告

当然,您可以省去最初的查询 SELECT @@warning_count, ,这将为您节省每次执行的查询,但我将其包含在内是为了迂腐的完整性。

其他提示

首先,你应该 关闭警告 这样您的访客就看不到您的 MySQL 错误。第二,当你打电话时 mysql_query(), ,你应该检查它是否返回 false。如果是这样,请致电 mysql_errno() 找出问题所在。将返回的数字与错误代码相匹配 这一页.

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

错误:第1169章23000 (ER_DUP_UNIQUE)

信息:由于唯一约束,无法写入表“%s”

ini_set('mysql.trace_mode', 1)

可能就是您正在寻找的。

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

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

根据作业名称的数量,您可以将名称发送到包含表单的视图,并使用 javascript 告诉用户所采用的名称。

如果这对您来说没有意义,那么总结一下我的观点是:不要将您的程序和/或用户设计为尝试执行非法操作并在执行时捕获错误并进行处理。恕我直言,最好将系统设计为不产生错误。将错误保留为实际错误:)

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

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

所以我想使用 mysqli_affected_rows() 也不能指望找到这样的警告,除非你有类似的东西 update_time 表中的列在更新时将始终分配新的时间戳值。不过,这种解决方法似乎有点笨拙。

您可以使用 mysqli 语句错误号检测唯一键违规。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 可以获得警告,并且比使用 mysql 更有效。

这是手册上建议的代码 在 php.net 上的 mysqli->warning_count 属性:

$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");
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top