W3docs

Подробное руководство по функции mysqli_sqlstate в PHP

Узнайте, как mysqli_sqlstate() возвращает коды SQLSTATE в PHP, чем отличается от mysqli_errno() и как использовать её в режиме исключений.

При работе с MySQL в PHP через расширение mysqli вам нужен надёжный способ выяснить, почему запрос завершился неудачно. Функция mysqli_sqlstate() возвращает код ошибки SQLSTATE для последней выполненной операции MySQL — стандартизированный переносимый код, указывающий категорию ошибки.

В этом руководстве объясняется, что такое SQLSTATE, чем mysqli_sqlstate() отличается от MySQL-специфичной mysqli_errno(), какие коды встречаются чаще всего и как правильно использовать эту функцию (в том числе в современном режиме PHP с исключениями).

Что такое SQLSTATE?

SQLSTATE — это пятисимвольный код ошибки, определённый стандартом ANSI/ISO SQL. Поскольку он является частью стандарта, а не изобретением MySQL, один и тот же код означает примерно одно и то же в разных СУБД, что делает его более переносимым, чем vendor-специфичные номера ошибок.

Пять символов разделены на две части:

  • Первые два символа обозначают класс ошибки. Например, класс 00 означает успех, 01 — предупреждение, а 42 — нарушение синтаксиса или правил доступа.
  • Последние три символа — это подкласс, который уточняет проблему.

Таким образом, 42S02 («базовая таблица или представление не найдено») относится к классу 42 (нарушение синтаксиса/доступа) с подклассом S02.

Синтаксис

mysqli_sqlstate(mysqli $connection): string

mysqli_sqlstate() принимает один аргумент — объект соединения, возвращаемый mysqli_connect(), — и возвращает строку:

  • Пустую, но заполненную нулями строку "00000", если последняя операция выполнена успешно.
  • Пятисимвольный код, например "42S02", при возникновении ошибки.

В объектно-ориентированном стиле это метод $connection->sqlstate.

SQLSTATE против mysqli_errno: что выбрать?

Эти две функции отвечают на разные вопросы, и зачастую нужны обе:

ФункцияВозвращаетХарактер
mysqli_sqlstate()5-символьную строку, например "42S02"Стандарт ANSI/ISO — переносим между СУБД
mysqli_errno()Целое число, например 1146MySQL-специфичный — более детальный, но не переносимый
mysqli_error()Читаемое сообщениеОписательный текст для логирования/отладки

Практическое правило: используйте ветвление на основе mysqli_sqlstate(), когда хотите, чтобы код пережил смену СУБД; обращайтесь к mysqli_errno(), когда нужно различить MySQL-специфичные ситуации. mysqli_error() используйте для сообщения в лог.

Полный пример

Код ниже подключается к базе данных, выполняет запрос к несуществующей таблице и выводит все три диагностических значения:

<?php

$connection = mysqli_connect('localhost', 'user', 'password', 'mydatabase');

if (!$connection) {
    die('Connection failed: ' . mysqli_connect_error());
}

$sql = "SELECT * FROM table_that_does_not_exist";

if (mysqli_query($connection, $sql)) {
    echo "Query executed successfully.";
} else {
    echo "SQLSTATE: " . mysqli_sqlstate($connection) . "\n";
    echo "Errno:    " . mysqli_errno($connection) . "\n";
    echo "Message:  " . mysqli_error($connection) . "\n";
}

// Typical output:
// SQLSTATE: 42S02
// Errno:    1146
// Message:  Table 'mydatabase.table_that_does_not_exist' doesn't exist

Обратите внимание, как переносимый SQLSTATE (42S02) и MySQL-специфичный номер ошибки (1146) описывают одну и ту же проблему с разной степенью детализации.

Распространённые коды SQLSTATE

Это коды, с которыми вы, скорее всего, будете сталкиваться в повседневной работе с PHP и MySQL:

SQLSTATEЗначение
00000Успех — ошибки нет
23000Нарушение ограничения целостности (например, дублирующийся ключ, ошибка внешнего ключа)
42000Синтаксическая ошибка или нарушение правил доступа
42S02Базовая таблица или представление не найдено
42S22Столбец не найден
HY000Общая ошибка (используется, когда нет более конкретного кода)
08S01Сбой связи / разрыв соединения

Ветвление на основе этих кодов позволяет реагировать осмысленно — например, обрабатывать ошибку 23000 с дублирующимся ключом как «запись уже существует», а не как критическую ошибку:

<?php

$sql = "INSERT INTO users (email) VALUES ('[email protected]')";

if (!mysqli_query($connection, $sql)) {
    if (mysqli_sqlstate($connection) === '23000') {
        echo "That email address is already registered.";
    } else {
        echo "Unexpected database error: " . mysqli_error($connection);
    }
}

Использование в режиме исключений

Современный PHP (8.1+) включает отчёты об ошибках MySQL по умолчанию, поэтому неудачный запрос выбрасывает исключение mysqli_sql_exception вместо возврата false. В этом режиме SQLSTATE читается из метода getSqlState() исключения, а не через вызов mysqli_sqlstate() после факта:

<?php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

try {
    $connection = mysqli_connect('localhost', 'user', 'password', 'mydatabase');
    mysqli_query($connection, "SELECT * FROM missing_table");
} catch (mysqli_sql_exception $e) {
    echo "SQLSTATE: " . $e->getSqlState() . "\n"; // e.g. 42S02
    echo "Code:     " . $e->getCode() . "\n";     // e.g. 1146
    echo "Message:  " . $e->getMessage();
}

Если вы вызываете mysqli_sqlstate() непосредственно после перехваченного исключения, это тоже работает — но внутри блока try/catch чтение кода из объекта исключения чище и не требует повторного обращения к состоянию соединения.

Подводные камни

  • Функция отражает только последнюю операцию. Каждый новый запрос перезаписывает предыдущий SQLSTATE. Читайте его сразу после нужного вызова — до выполнения любых других операций на том же соединении.
  • "00000" означает успех, а не ошибку. Не воспринимайте непустой возврат как сбой; успешная операция возвращает строку из нулей, а не "".
  • У неудачного соединения нет SQLSTATE. Если сам mysqli_connect() завершился неудачно, объекта соединения для запроса не существует — используйте mysqli_connect_error() для диагностики проблем подключения.

Заключение

mysqli_sqlstate() возвращает переносимый, основанный на стандартах код SQLSTATE для последней операции MySQL, дополняя MySQL-специфичный mysqli_errno() и читаемый mysqli_error(). Используйте ветвление по SQLSTATE, когда хотите получить независимую от СУБД обработку ошибок; переходите к getSqlState() исключения в режиме исключений PHP по умолчанию; и всегда читайте код сразу после описываемой им операции.

Практика

Практика
Что возвращает функция mysqli_sqlstate() в PHP?
Что возвращает функция mysqli_sqlstate() в PHP?
Was this page helpful?