MySQLi 预准备语句错误报告 [duplicate]

MySQLi prepared statements error reporting [duplicate]

提问人:Columbo 提问时间:3/31/2010 最后编辑:MPelletierColumbo 更新时间:9/22/2022 访问量:148062

问:

我正试图了解 MySQli,但我对错误报告感到困惑。 我正在使用 MySQLi 'prepare' 语句的返回值来检测执行 SQL 时的错误,如下所示:

$stmt_test =  $mysqliDatabaseConnection->stmt_init();
if($stmt_test->prepare("INSERT INTO testtable VALUES (23,44,56)"))
{
 $stmt_test->execute();
 $stmt_test->close();
}
else echo("Statement failed: ". $stmt_test->error . "<br>");

但是,prepare 语句的返回值是否只检测 SQL 语句的准备中是否存在错误,而不检测执行错误?如果是这样,我应该更改我的执行行以标记错误,如下所示:

if($stmt_test->execute()) $errorflag=true;

然后,为了安全起见,我还应该在语句执行后执行以下操作:

if($stmt_test->errno) {$errorflag=true;}

...或者我是否可以开始,并且MySQLi prepare'语句上的返回值捕获与它定义的查询的完整执行相关的所有错误?

谢谢 C

php mysql mysqli 预备语句

评论

0赞 VolkerK 3/31/2010
当查询字符串中没有变量部分时,为什么首先使用 prepare/execute() 而不是 query()?或者这只是一个过于简化的例子?
0赞 Columbo 3/31/2010
是的,对不起。它被简化以显示我如何难以理解从哪里从准备好的 staement 获得明确的错误报告。

答:

6赞 andyface 3/31/2010 #1

不确定这是否回答了您的问题。对不起,如果不是

要从 mysql 数据库获取有关查询的错误报告,您需要使用连接对象作为焦点。

所以:

echo $mysqliDatabaseConnection->error

将回显从MySQL发送的有关您的查询的错误。

希望能有所帮助

评论

0赞 Columbo 3/31/2010
谢谢。因此,如果我请求实际连接对象的错误,那么它将为我提供该连接的最后一个错误。由于只有在前面的所有步骤都成功的情况下,执行才会成功,因此这将告诉我是否一切顺利。我想也可以通过检查下面由 Col Shrapnel 认可的执行命令的错误来生成相同的结果。因此,我认为检查准备语句的成功/失败标志没有真正的目的,这是对的吗?
0赞 andyface 4/6/2010
我想你可能已经在上面有了答案,但出于礼貌,你仍然会回答。正如 VolekrK 所说,从本质上讲,Prepare 可能会失败,但它不会返回 mysql 错误。因此,您需要通过获取 mysql 连接错误来找出 prepare 失败的原因,这将为您提供 prepare 语句中查询失败的指示。我不确定执行命令错误。
165赞 VolkerK 3/31/2010 #2

mysqli 的每个方法都可能失败。幸运的是,现在mysqli可以向你报告每一个问题,你所需要的只是问。只需将这一行添加到连接代码中,

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

在那之后,每个错误都会显露出来。无需测试任何返回值,只需立即编写语句即可:

$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
$stmt->bind_param('iii', $x, $y, $z);
$stmt->execute();

当错误发生在任何步骤时,它将抛出一个通常的PHP异常,可以像任何其他PHP错误一样处理或报告。只要确保你配置了正确的PHP错误报告,即在开发服务器上,错误显示在屏幕上,而在生产服务器上,错误永远不会显示,而是记录下来。

评论

2赞 Columbo 3/31/2010
谢谢。我刚刚做了一些测试,可以看到你在说什么。如果我创建一个查询,将重复的主键值插入到表中,则仅检查准备不会显示插入失败。另一方面,如果我不检查准备,那么执行将永远不会发生(如果警告打开,我会收到一些警告)。所以我可以看出你是对的。谢谢。
0赞 VolkerK 3/31/2010
哦,是的,约束就是一个很好的例子。如果可能的话,我会再给这个问题+1;-)
2赞 Accountant م 1/16/2017
如果由于类型定义字符串中的元素数与绑定变量数不匹配而失败。它会触发E_WARNING错误。并且您不会在 $stmt->error 属性中找到该错误bind_param()
0赞 Your Common Sense 9/22/2022
@Accountant م 幸运的是,这种滋扰已经过去了。在现代 PHP 版本中,bind_param 也会抛出异常。
22赞 cmc 12/13/2013 #3

完整性

您需要同时检查 和 .如果它们为 false,则需要分别输出 或。$mysqli$statement$mysqli->error$statement->error

效率

对于可能终止的简单脚本,我使用简单的单行代码来触发消息的 PHP 错误。对于更复杂的应用程序,应改为激活错误警告系统,例如通过抛出异常。

使用示例 1:简单脚本

# This is in a simple command line script
$mysqli = new mysqli('localhost', 'buzUser', 'buzPassword');
$q = "UPDATE foo SET bar=1";
($statement = $mysqli->prepare($q)) or trigger_error($mysqli->error, E_USER_ERROR);
$statement->execute() or trigger_error($statement->error, E_USER_ERROR);

使用示例 2:应用程序

# This is part of an application
class FuzDatabaseException extends Exception {
}

class Foo {
  public $mysqli;
  public function __construct(mysqli $mysqli) {
    $this->mysqli = $mysqli;
  }
  public function updateBar() {
    $q = "UPDATE foo SET bar=1";
    $statement = $this->mysqli->prepare($q);
    if (!$statement) {
      throw new FuzDatabaseException($mysqli->error);
    }

    if (!$statement->execute()) {
      throw new FuzDatabaseException($statement->error);
    }
  }
}

$foo = new Foo(new mysqli('localhost','buzUser','buzPassword'));
try {
  $foo->updateBar();
} catch (FuzDatabaseException $e)
  $msg = $e->getMessage();
  // Now send warning emails, write log
}

评论

0赞 Your Common Sense 12/13/2013
1. die() 永远不应该使用。2. MySQLI能够自己抛出异常,参见mysqli_report() 2.在每个数据库驱动的函数之后编写“发送警告电子邮件,写入日志”的代码是非常多余的
0赞 Your Common Sense 12/13/2013
无论如何,您永远不应该按原样使用 mysqli API,而只能包装在一些更高级别的库中。
3赞 Fernando Silva 1/4/2014
提到 $mysqli->error 和 $statement->error 只是挽救了我的一天,谢谢^^
2赞 cmc 1/7/2014
@FernandoSilva很高兴听到费尔南多,你刚刚做了我的!
1赞 cmc 1/9/2014
@YourCommonSense 对于应用程序来说,是的,减少样板可能是件好事,但如何最好地做到这一点取决于应用程序。这个例子当然是一个不错的起点。