MySQLi prepared statements error reporting [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Estoy tratando de obtener mi cabeza alrededor de MySQli y estoy confundido por el informe de errores. Estoy usando el valor de retorno de la instrucción MySQLi 'prepare' para detectar errores al ejecutar SQL, así:

$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>");

Pero, es el ¿el valor devuelto de la instrucción prepare solo detecta si hay un error en la preparación de la instrucción SQL y no detecta errores de ejecución? Si es así, por lo tanto, debería cambiar mi línea de ejecución para marcar errores también de esta manera:

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

Y luego, solo para estar seguro, también debo hacer lo siguiente después de que la declaración se haya ejecutado:

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

...O estaba bien para empezar y el valor devuelto en la instrucción MySQLi prepare' captura todos los errores asociados con el ejecución de la consulta que define?

Gracias C

Author: MPelletier, 2010-03-31

3 answers

Escribí esto dos veces antes en los últimos dos días (así que para mí es un duplicado a pesar de que las preguntas comenzaron un poco diferente).

Cada método de mysqli puede fallar. Debe probar cada valor devuelto. Si uno falla, piense si tiene sentido continuar con un objeto que no está en el estado que espera que esté. (Potencialmente no en un estado "seguro", pero creo que eso no es un problema aquí.)

Dado que solo se almacena el mensaje de error de la última operación conexión / sentencia es posible que pierda información sobre lo que causó el error si continúa después de que algo salió mal. Es posible que desee utilizar esa información para dejar que el script decida si desea intentarlo de nuevo (solo un problema temporal), cambiar algo o rescatar por completo (e informar de un error). Y hace que la depuración sea mucho más fácil.

$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();

Editar: solo unas pocas notas seis años después....
La extensión mysqli es perfectamente capaz de reportar operaciones que resultan en un (mysqli) código de error que no sea 0 a través de excepciones, consulte mysqli_driver:: report report_mode.
die () es muy, muy crudo y ya no lo usaría ni siquiera para ejemplos como este.
Así que por favor, solo quiten el hecho de que todas y cada una de las operaciones (mysql) pueden fallar por una serie de razones; incluso si exactamente lo mismo salió bien mil veces antes....

 105
Author: VolkerK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 20:59:38

Exhaustividad

Debe verificar tanto $mysqli como $statement. Si son false, debe mostrar $mysqli->error o $statement->error respectivamente.

Eficiencia

Para scripts simples que pueden terminar, uso simples de una línea que desencadenan un error de PHP con el mensaje. Para una aplicación más compleja, se debe activar un sistema de advertencia de error, por ejemplo lanzando una excepción.

Ejemplo de uso 1: Simple script

# 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);

Ejemplo de uso 2: Aplicación

# 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
}
 13
Author: cmc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-08 23:41:34

No estoy seguro de si esto responde a tu pregunta o no. Lo siento si no

Para obtener el error reportado desde la base de datos mysql sobre su consulta, debe usar su objeto de conexión como foco.

Así que:

echo $mysqliDatabaseConnection->error

Se haría eco del error que se envía desde mysql sobre su consulta.

Esperanza que ayuda

 4
Author: andyface,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-31 12:04:52