MySQLi编写了语句错误报告

Col*_*mbo 58 php mysql mysqli prepared-statement

我正试图绕过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>");
Run Code Online (Sandbox Code Playgroud)

但是,prepare语句的返回值是仅检测SQL语句的预处理中是否存在错误而未检测到执行错误?如果是这样,我应该更改我的执行行以标记错误,如下所示:

if($stmt_test->execute()) $errorflag=true;
Run Code Online (Sandbox Code Playgroud)

然后只是为了安全我应该在语句执行后执行以下操作:

if($stmt_test->errno) {$errorflag=true;}
Run Code Online (Sandbox Code Playgroud)

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

谢谢C.

Vol*_*erK 121

我在过去两天之前写了两次这样的话(对我而言,即使问题开始有点不同,也是重复的).

mysqli的每种方法都可能失败.您应该测试每个返回值.如果一个失败,请考虑继续使用不符合您期望状态的对象是否有意义.(可能不是处于"安全"状态,但我认为这不是问题.)

因为只有在最后操作的错误信息被存储在每个连接/声明可能会丢失有关的信息是什么,如果你继续后出了问题造成的错误.您可能希望使用该信息让脚本决定是再次尝试(仅限临时问题),更改内容还是完全拯救(并报告错误).它使调试变得更容易.

$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
// prepare() can fail because of syntax errors, missing privileges, ....
if ( false===$stmt ) {
  // and since all the following operations need a valid/ready statement object
  // it doesn't make sense to go on
  // you might want to use a more sophisticated mechanism than die()
  // but's it's only an example
  die('prepare() failed: ' . htmlspecialchars($mysqli->error));
}

$rc = $stmt->bind_param('iii', $x, $y, $z);
// bind_param() can fail because the number of parameter doesn't match the placeholders in the statement
// or there's a type conflict(?), or ....
if ( false===$rc ) {
  // again execute() is useless if you can't bind the parameters. Bail out somehow.
  die('bind_param() failed: ' . htmlspecialchars($stmt->error));
}

$rc = $stmt->execute();
// execute() can fail for various reasons. And may it be as stupid as someone tripping over the network cable
// 2006 "server gone away" is always an option
if ( false===$rc ) {
  die('execute() failed: ' . htmlspecialchars($stmt->error));
}

$stmt->close();
Run Code Online (Sandbox Code Playgroud)

编辑:只是几个音符,六年后....
mysqli扩展是完全有能力报告说,导致(mysqli的)错误0以外的通过异常的代码操作,见mysqli_driver :: $ report_mode.
die()真的非常粗糙,即使是像这样的例子也不会用它.
所以,请注意,每个(mysql)操作都会因为多种原因而失败; 甚至,如果同样的事情进行得很顺利前一千倍....

  • 谢谢.我刚做了一些测试,可以看到你在说什么.如果我创建一个问题,将重复的主键值插入表中,那么仅检查准备将不会显示插入失败.另一方面,如果我不检查准备,则执行将永远不会发生(如果警告已打开,我会收到一些警告).所以我可以看出你是对的.谢谢. (2认同)
  • 如果“bind_param()”由于类型定义字符串中的元素数量与绑定变量的数量不匹配而失败。它会触发 E_WARNING 错误。并且您不会在 $stmt-&gt;error 属性中找到该错误 (2认同)

cmc*_*cmc 15

完整性

你需要检查两者$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);
Run Code Online (Sandbox Code Playgroud)

用法示例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
}
Run Code Online (Sandbox Code Playgroud)

  • 提到$ mysqli->错误AND $ statement->错误只是保存了我的一天,这是^^ (3认同)
  • @FernandoSilva很高兴听到费尔南多,你刚刚成了我的! (2认同)

and*_*ace 6

不确定这是否回答了您的问题。抱歉,如果没有

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

所以:

echo $mysqliDatabaseConnection->error
Run Code Online (Sandbox Code Playgroud)

将回显从 mysql 发送的关于您的查询的错误。

希望有帮助