web-dev-qa-db-de.com

MySQLi hat Fehlerberichte für Anweisungen vorbereitet

Ich versuche, MySQli in den Griff zu bekommen, und bin durch die Fehlermeldung verwirrt. Ich verwende den Rückgabewert der MySQLi-Anweisung 'prepare', um Fehler bei der Ausführung von SQL zu erkennen:

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

Wird der Rückgabewert der prepare-Anweisung jedoch nur erkannt, wenn ein Fehler in der Vorbereitung der SQL-Anweisung vorliegt, und werden keine Ausführungsfehler erkannt? Wenn ja, sollte ich meine Execute-Zeile daher auch so ändern, dass sie Fehler kennzeichnet:

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

Und dann, um sicher zu gehen, sollte ich auch Folgendes tun, nachdem die Anweisung ausgeführt wurde:

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

... Oder war ich zu Beginn in Ordnung, und der Rückgabewert in der MySQLi-Anweisung prepare 'erfasst alle Fehler, die mit der vollständigen Ausführung der von ihr definierten Abfrage zusammenhängen?

Danke c

57
Columbo

Ich habe das in den letzten zwei Tagen zweimal geschrieben (für mich ist es ein Duplikat, obwohl die Fragen etwas anders angefangen haben).

Jede Methode von mysqli kann fehlschlagen. Sie sollten jeden Rückgabewert testen. Wenn einer fehlschlägt, überlegen Sie, ob es sinnvoll ist, mit einem Objekt fortzufahren, das sich nicht in dem erwarteten Zustand befindet. (Möglicherweise nicht in einem "sicheren" Zustand, aber ich denke, das ist hier kein Problem.)

Da nur die Fehlermeldung für die letzte Operation pro Verbindung/Anweisung gespeichert wird, können Sie Informationen darüber verlieren, was den Fehler verursacht hat , wenn Sie fortfahren, nachdem ein Fehler aufgetreten ist. Sie können diese Informationen verwenden, um das Skript entscheiden zu lassen, ob es es erneut versucht (nur ein vorübergehendes Problem), etwas ändert oder einen vollständigen Bailout durchführt (und einen Fehler meldet). Und es macht das Debuggen viel einfacher.

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

edit: nur ein paar noten sechs jahre später ....
Die mysqli-Erweiterung ist perfekt in der Lage, Vorgänge zu melden, die über Ausnahmen zu einem (mysqli-) Fehlercode ungleich 0 führen, siehe mysqli_driver :: $ report_mode .
die () ist wirklich sehr, sehr grob und ich würde es nicht einmal mehr für Beispiele wie dieses verwenden.
Nehmen Sie also bitte nur die Tatsache weg, dass jede (mysql) Operation aus mehreren Gründen scheitern; sogar wenn genau dasselbe tausendmal gut gegangen ist ...

118
VolkerK

Vollständigkeit

Sie müssen sowohl $mysqli Als auch $statement Überprüfen. Wenn sie falsch sind, müssen Sie $mysqli->error Bzw. $statement->error Ausgeben.

Effizienz

Für einfache Skripte, die möglicherweise enden, verwende ich einfache Einzeiler, die mit der Meldung einen PHP) - Fehler auslösen. Für eine komplexere Anwendung sollte stattdessen ein Fehlerwarnsystem aktiviert werden, z. B. durch Werfen eine Ausnahme.

Anwendungsbeispiel 1: Einfaches Skript

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

Anwendungsbeispiel 2: Anwendung

# 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
}
15
cmc

Nicht sicher, ob dies Ihre Frage beantwortet oder nicht. Entschuldigung wenn nicht

Um den Fehler zu Ihrer Abfrage aus der mysql-Datenbank zu erhalten, müssen Sie Ihr Verbindungsobjekt als Fokus verwenden.

so:

echo $mysqliDatabaseConnection->error

würde den von MySQL über Ihre Anfrage gesendeten Fehler wiedergeben.

Hoffentlich hilft das

4
andyface