Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Artfiles.de
Bietet Serviceorientierte Internetdienstleistungen...
https://www.Artfiles.de
Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains und...
https://www.Hosterplus.de
 
 
 

PHP mysqli_errno() Function: Exceptions und Fehlernummern

Sie befinden sich: Home > Php Tutorial > PHP mysqli_errno() Function...

PHP mysqli_errno() Function: Exceptions und Fehlernummern
Veröffentlicht am:
05.10.2026
Hits / Besucher:
7
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Ein Anmeldeformular soll bei einer schon vergebenen E-Mail-Adresse keinen Datenbankauszug zeigen, sondern einen Satz, den ein Besucher versteht. Damit das gelingt, muss der Code diesen einen Fehler von allen anderen trennen, bevor er irgendetwas ausgibt. PHP mysqli_errno liefert genau die Zahl, an der sich ein doppelter Eintrag von einer fehlenden Tabelle oder einem Deadlock unterscheidet. Der Weg zur Abfrage selbst, also Verbindung, Platzhalter und Ausführung, steht im Tutorial zu Prepared Statements und wird hier vorausgesetzt.

Illustration zum Tutorial: PHP mysqli_errno() Function: Exceptions und Fehlernummern

Die Nummer ist die einzige Auskunft, die sich weder mit dem Schema noch mit der Sprache des Servers ändert. Alles andere an einem Datenbankfehler tut das sehr wohl.

Was PHP mysqli_errno() liefert

mysqli_errno() gibt die Fehlernummer der zuletzt ausgeführten Operation auf dieser Verbindung heraus. Lief alles glatt, steht dort eine Null. Der Wert hängt an der Verbindung, nicht an einer einzelnen Abfrage, und jede neue Operation überschreibt ihn. Wer die Nummer braucht, liest sie deshalb sofort aus und nicht drei Zeilen später.

Zwei Nachbarfunktionen beantworten dieselbe Frage auf andere Weise. mysqli_error() liefert den Meldungstext, mysqli_sqlstate() den genormten Zustandscode. Nach einer erfolgreichen Abfrage sehen die drei Werte so aus:

<?php

$db->query('SELECT 1');

var_dump($db->errno); /* int(0) */
var_dump($db->error); /* string(0) "" */
var_dump($db->sqlstate); /* string(5) "00000" */

Drei Sorten von Leere: die Null, der leere Text und die Zeichenkette aus fünf Nullen. Wer auf Erfolg prüft, nimmt die Null aus mysqli_errno().

Syntax, Parameter und Rückgabewert im Original

<?php

mysqli_errno(mysqli $mysql): int
mysqli_connect_errno(): int
mysqli_sqlstate(mysqli $mysql): string

/* mysql: a connection returned by
mysqli_connect() or new mysqli()
errno returns the error code of the most
recent function call, 0 on success
connect_errno takes no argument and
reports the last connection attempt
sqlstate returns the five character
ANSI SQL state, '00000' on success
object style: $db->errno, $db->sqlstate */

An der Signatur hängen zwei Punkte, die später Zeit sparen. Erstens ist der Rückgabetyp eine Ganzzahl und nie false, geprüft wird also auf Ungleichheit zu null. Zweitens verlangt PHP mysqli_errno() eine Verbindung als Parameter, während mysqli_connect_errno() ohne Argument auskommt. Genau darin liegt der Unterschied zwischen einem Fehler beim Arbeiten und einem Fehler beim Verbinden.

Seit PHP 8.1 wirft mysqli Exceptions von allein

Bis PHP 8.0 gab ein gescheitertes mysqli_query() nur false zurück. Seit PHP 8.1 ist der Meldemodus MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT voreingestellt, und ein Fehler kommt als mysqli_sql_exception. Ein Beispiel der Form if (!$ergebnis) { echo mysqli_errno($db); } erreicht seine eigene Ausgabe nie.

flowchart TD
    A[Abfrage absetzen] --> B{Fehler?}
    B -- nein --> C[errno = 0]
    B -- ja --> D{Modus wirft?}
    D -- ja --> E[mysqli_sql_exception]
    E --> F[getCode]
    D -- nein --> G[Rückgabe false]
    G --> H[mysqli_errno]
    F --> I[Nummer auswerten]
    H --> I

Beide Wege führen zur selben Zahl, und das ist die gute Nachricht. An einem doppelten Primärschlüssel gemessen liefert $e->getCode() die 1062, $e->getSqlState() die Zeichenkette 23000, und PHP mysqli_errno() meldet im catch-Block ebenfalls 1062. Die Ausnahmeklasse erbt von RuntimeException, ein vorhandener Fehlerbehandler fängt sie also mit.

<?php

/* Weg 1: Ausnahme, Standard seit PHP 8.1 */
try {
$db->query($insert);
} catch (mysqli_sql_exception $e) {
echo $e->getCode(); /* 1062 */
echo $e->getSqlState(); /* 23000 */
echo mysqli_errno($db); /* auch 1062 */
}

/* Weg 2: alter Stil, Meldungen abgeschaltet */
mysqli_report(MYSQLI_REPORT_OFF);
if ($db->query($insert) === false) {
echo mysqli_errno($db); /* 1062 */
}

Welcher Weg der richtige ist, entscheidet der umgebende Code. In einer Anwendung mit zentralem Fehlerbehandler sind Ausnahmen die bessere Wahl. In einem alten Skript, das an vierzig Stellen auf false prüft, ist ein einzelnes mysqli_report(MYSQLI_REPORT_OFF) am Anfang ehrlicher als vierzig halbfertige Umbauten. PHP mysqli_errno() funktioniert in beiden Welten gleich.

Nummer, Text oder Zustandscode

Drei Quellen, drei Eignungen. Der Meldungstext eines Duplikats lautet in der Testdatenbank Duplicate entry '1' for key 'zz_t.PRIMARY' und trägt Tabellen- und Schlüsselnamen in sich. Benennt jemand die Tabelle um, passt der Vergleich nicht mehr. Schlimmer ist es bei Verbindungsfehlern: Die 2002 kommt auf einem deutschsprachigen Windows mit dem Satz „Es konnte keine Verbindung hergestellt werden“, weil dieser Text vom Betriebssystem stammt. Wer auf „Connection refused“ prüft, findet dort nichts. Die Nummer war beide Male dieselbe.

Quelle Was herauskommt Bei Erfolg Taugt zum Verzweigen?
mysqli_errno() Ganzzahl, etwa 1062 0 Ja. Sie bleibt über Sprachen und Schemas hinweg gleich.
mysqli_error() Meldungstext mit Tabellen- und Schlüsselnamen leerer Text Nein. Gut fürs Protokoll, untauglich als Bedingung.
mysqli_sqlstate() fünfstelliger genormter Zustandscode '00000' Nur grob. 1062, 1048, 1451 und 1452 tragen alle die 23000.

Der Zustandscode wirkt präziser, weil er genormt ist, und ist doch der gröbere Wert. Vier verschiedene Lagen teilen sich die 23000: ein Duplikat, ein fehlendes Pflichtfeld, eine Vaterzeile mit Kindern und eine Kindzeile ohne Vater. Wer darauf verzweigt, behandelt alle vier gleich. Seine Stärke liegt beim Wechsel des Datenbanksystems, denn dort bleibt er stabil, während die Fehlernummern herstellerspezifisch sind.

Ins Protokoll gehören alle drei Angaben, und zwar als getrennte Felder. Wer sie zu einem Satz verschmilzt, kann später nicht mehr nach der Nummer filtern. mysqli_error_list() liefert diese drei Felder fertig als Array. Wie ein Protokoll überhaupt aufgesetzt und ausgewertet wird, steht im Tutorial zu error_log().

<?php

$eintrag = [
'errno' => mysqli_errno($db),
'sqlstate' => mysqli_sqlstate($db),
'error' => mysqli_error($db),
'sql' => $sql,
];
error_log(json_encode($eintrag));

Fehler beim Verbindungsaufbau mit mysqli_connect_errno()

Solange keine Verbindung steht, gibt es kein Objekt, das PHP mysqli_errno() entgegennehmen könnte. Dafür ist mysqli_connect_errno() zuständig. Zwei Fallen lauern hier. Erstens liefert mysqli_connect_error() nach einem erfolgreichen Aufbau nicht den leeren Text, sondern null. Zweitens gibt new mysqli() bei abgeschaltetem Meldemodus auch bei falschem Passwort ein Objekt zurück. Eine Prüfung auf if (!$db) greift dort nie.

<?php

mysqli_report(MYSQLI_REPORT_OFF);
$db = @new mysqli($host, $user, $pass, $name);

/* 1045 falsches Passwort
1044 kein Zugriff auf diese Datenbank
2002 Server nicht erreichbar */
if ($db->connect_errno !== 0) {
error_log('DB ' . $db->connect_errno
. ': ' . $db->connect_error);
exit('Datenbank nicht erreichbar.');
}

Praxis 1: doppelter Eintrag mit 1062 abfangen

Der klassische Fall. Statt vorher zu fragen, ob die Adresse vergeben ist, schreibt der Code einfach und fängt den einen Fehler ab. Das spart eine Abfrage und schließt die Lücke zwischen Prüfung und Einfügen, in der sich zwei gleichzeitige Anmeldungen überholen. Wichtig ist der zweite Teil der Bedingung: Jede andere Nummer fliegt weiter nach oben.

<?php

try {
$stmt = $db->prepare(
'INSERT INTO nutzer (mail) VALUES (?)'
);
$stmt->bind_param('s', $mail);
$stmt->execute();
$hinweis = 'Konto angelegt.';
} catch (mysqli_sql_exception $e) {
if ($e->getCode() !== 1062) {
throw $e;
}
$hinweis = 'Diese Adresse ist vergeben.';
}

Eine Einschränkung gehört dazu: Die 1062 verrät nicht, welcher Schlüssel kollidiert ist. Gemessen melden der verletzte Primärschlüssel und der verletzte eindeutige Index dieselbe Nummer. Wer zwei eindeutige Spalten hat, etwa Adresse und Benutzername, erfährt aus PHP mysqli_errno() also nicht, welches Feld der Besucher ändern soll. Dann bleibt die gezielte Vorabprüfung oder das Auslesen des Schlüsselnamens aus der Meldung, und Letzteres bindet den Code ans Schema.

Praxis 2: INSERT-Import, der nur Dubletten überspringt

Ein nächtlicher Import soll durchlaufen, auch wenn einzelne Zeilen schon in der Tabelle stehen. Alles andere muss ihn sofort stoppen, denn ein Import, der stumm die Hälfte verwirft, ist schlimmer als gar keiner. Genau eine Nummer wird geduldet.

<?php

$uebersprungen = 0;

foreach ($zeilen as $zeile) {
$stmt->bind_param('ss', $zeile[0], $zeile[1]);
try {
$stmt->execute();
} catch (mysqli_sql_exception $e) {
if ($e->getCode() !== 1062) {
throw $e;
}
$uebersprungen++;
}
}
echo "$uebersprungen Dubletten ignoriert";

Vorbereitete Anweisungen haben eigene Auskunftsfunktionen. Nach einem gescheiterten mysqli_stmt_execute() liefern mysqli_stmt_errno($stmt) und mysqli_errno($db) denselben Wert, hier 1062. Dasselbe gilt für mysqli_stmt_sqlstate() gegenüber mysqli_sqlstate(). Der Unterschied zählt trotzdem, denn mysqli_prepare() kann selbst scheitern, und dann gibt es noch kein Statement. Gemessen steht dort 1146 an der Verbindung bereit.

Praxis 3: Deadlock erkennen und wiederholen

Manche Fehler bedeuten nicht, dass der Vorgang falsch war, sondern dass er Pech hatte. Zwei Verbindungen sperren zwei Zeilen in umgekehrter Reihenfolge, der Server erklärt eine zum Opfer und bricht sie ab. Gemessen mit zwei Verbindungen auf InnoDB: die eine bekommt 1213 mit Zustandscode 40001 und dem Text Deadlock found when trying to get lock; try restarting transaction, die andere läuft mit einer Fehlernummer von 0 durch. Verwandt damit ist 1205 mit Zustandscode HY000, die Sperrzeitüberschreitung. Wie ein Vorgang überhaupt umschlossen wird, steht im Tutorial zu beginTransaction, commit und rollBack.

<?php

$wiederholbar = [1213, 1205];

for ($versuch = 1; $versuch <= 3; $versuch++) {
try {
$db->begin_transaction();
buchen($db, $von, $nach, $betrag);
$db->commit();
break;
} catch (mysqli_sql_exception $e) {
$db->rollback();
$code = $e->getCode();
if (!in_array($code, $wiederholbar, true)) {
throw $e;
}
usleep(50000 * $versuch);
}
}

Die Liste der wiederholbaren Nummern muss kurz bleiben. Ein Syntaxfehler ist beim dritten Versuch derselbe Syntaxfehler, und eine Schleife, die jede Fehlernummer wiederholt, verwandelt einen Tippfehler in Dauerlast. Die wachsende Wartezeit ist kein Schmuck: Ohne sie treffen die beiden Verbindungen sofort wieder aufeinander.

Die Nummern aus dem Alltag

Nummern unter 2000 kommen vom MySQL-Server, Nummern ab 2000 von der Clientbibliothek. Das erklärt, warum 2006 kein SQL-Fehler ist: Die Abfrage war in Ordnung, die Leitung nicht. Alle Werte sind an PHP 8.4 gegen MySQL 8.0.46 nachgemessen.

Nummer SQLSTATE Bedeutung Sinnvolle Reaktion
1062 23000 Primärschlüssel oder eindeutiger Index verletzt Besucher informieren
1048 23000 NULL in einer Pflichtspalte Eingabeprüfung nachziehen
1451 23000 Vaterzeile hat noch Kinder Abhängige Datensätze zuerst
1452 23000 Kindzeile ohne passenden Vater Fremdschlüsselwert prüfen
1146 42S02 Tabelle gibt es nicht Migration fehlt
1213 40001 Deadlock, Transaktion abgebrochen Wiederholen
1205 HY000 Sperrzeitüberschreitung beim Warten Wiederholen
2002 HY000 Server nicht erreichbar, Meldung der Clientbibliothek Wartungsseite statt Fehlerausgabe
2006 HY000 Verbindung weggebrochen Neu verbinden

Beim Umstieg auf PDO lauert hier eine Vertauschung. PDOStatement::errorInfo() liefert ein Array, in dem an Position 0 der Zustandscode steht und an Position 1 die treiberspezifische Nummer, also das Gegenstück zu PHP mysqli_errno(). PDOException::getCode() gibt dagegen den Zustandscode heraus. Wer eine Verzweigung auf 1062 eins zu eins überträgt, vergleicht dort plötzlich gegen 23000. Mehr dazu im Vergleich von PDO und mysqli.

Was PHP mysqli_errno() nicht sieht

Die Funktion meldet Fehler, keine Auffälligkeiten. Das ist eine echte Grenze, und sie fällt genau dann auf, wenn Daten leise falsch in der Tabelle landen. Gemessen: SELECT CAST('abc' AS SIGNED) läuft mit einer Fehlernummer von 0 durch, obwohl MySQL den Wert verwirft. Die Auskunft steckt in mysqli_warning_count() und mysqli_get_warnings().

<?php

$db->query("SELECT CAST('abc' AS SIGNED)");

echo mysqli_errno($db); /* 0 */
echo mysqli_warning_count($db); /* 1 */

$w = mysqli_get_warnings($db);
echo $w->errno; /* 1292 */
echo $w->message;
/* Truncated incorrect INTEGER value: 'abc' */

Der zweite blinde Fleck wird gern falsch gedeutet. Ein UPDATE, das keine Zeile trifft, liefert 0 betroffene Zeilen bei einer Fehlernummer von 0. Das ist kein Fehler, sondern kein Treffer. Die dritte Falle liegt beim Aufräumen: Nach mysqli_close() wirft PHP mysqli_errno() den harten Fehler mysqli object is already closed. Wer im finally-Block schließt und danach protokolliert, baut sich genau das ein.

Fazit

Die Fehlernummer ist die einzige Auskunft, die sich nicht ändert, wenn jemand eine Spalte umbenennt oder der Server in einer anderen Sprache antwortet. PHP mysqli_errno() holt sie in einer Zeile, im catch-Block genauso wie nach einem false. Drei Bausteine daraus tragen weit: die freundliche Meldung bei 1062, der Import mit genau einer geduldeten Nummer und die Wiederholschleife für 1213 und 1205. Warnungen holt man sich getrennt, denn die sieht PHP mysqli_errno() nicht.

 


 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.