@@ERROR: примеры (SQL)

MS SQL Server: применение и особенности функции @@ERROR
Раздел: Функции управления системой
@@ERROR: int

Функция @@ERROR в MS SQL Server

Системная функция @@ERROR возвращает код последней выполненной инструкции языка Transact-SQL. Если выполнение прошло успешно, функция возвращает 0. Функция не принимает аргументов. Это скалярная функция, которая возвращает целочисленное значение (int).

Использование функции @@ERROR характерно для обработки ошибок в сценариях, где не применяется конструкция TRY...CATCH, а также для обратной совместимости с более ранними версиями SQL Server. Значение функции сбрасывается после каждого выполненного оператора, поэтому его необходимо проверять сразу после инструкции, которая может вызвать ошибку, или сохранять в локальную переменную для последующего анализа.

Возвращаемое значение представляет собой код ошибки. Код 0 означает успешное выполнение. Любое другое число соответствует конкретному сообщению об ошибке, информацию о котором можно получить из системного представления sys.messages.

Базовые примеры использования

Простейший пример проверки на ошибку деления на ноль.

SELECT 1/0;
SELECT @@ERROR AS ErrorCode;
Сообщение об ошибке 8134, уровень 16, состояние 1...

ErrorCode
---------
8134

Пример успешного выполнения и сохранения значения в переменную.

DECLARE @ErrorCode INT;
SELECT 1/1; -- Успешная операция
SET @ErrorCode = @@ERROR;
SELECT @ErrorCode AS LastErrorCode;
LastErrorCode
-------------
0

Использование в условной логике после оператора INSERT.

INSERT INTO NonExistentTable (ID) VALUES (1);
IF @@ERROR <> 0
    PRINT 'Произошла ошибка при вставке.';
Сообщение об ошибке 208, уровень 16...
Произошла ошибка при вставке.

Альтернативы в MS SQL Server

В современных версиях SQL Server предпочтительным методом обработки ошибок является конструкция TRY...CATCH. Внутри блока CATCH доступны системные функции, предоставляющие детальную информацию об ошибке:

  • ERROR_NUMBER(): Возвращает номер ошибки, аналогично @@ERROR.
  • ERROR_MESSAGE(): Возвращает полный текст сообщения об ошибке.
  • ERROR_SEVERITY(), ERROR_STATE(), ERROR_LINE(), ERROR_PROCEDURE(): Возвращают дополнительные сведения.

Функции внутри блока CATCH не сбрасываются после каждого оператора, что делает обработку более надежной и читаемой. Использование TRY...CATCH рекомендуется для нового кода.

Аналоги в других СУБД

MySQL: Использует обработчики DECLARE ... HANDLER и функции, такие как LAST_INSERT_ID() для конкретных задач, либо глобальные переменные, например, @@ERROR (устаревшая) или @@sqlstate. Более современный подход — обработка исключений в хранимых процедурах.

-- Пример в MySQL (используя старую переменную, не рекомендуется)
SELECT 1/0;
SELECT @@ERROR;
ERROR 1365 (22012): Division by 0
@@ERROR
1365

Oracle: Использует встроенные исключения и блок EXCEPTION в PL/SQL. Для получения кода ошибки применяется SQLCODE, а для текста — SQLERRM.

BEGIN
    INSERT INTO non_existent_table VALUES (1);
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Error Code: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('Error Message: ' || SQLERRM);
END;

PostgreSQL: Использует блок EXCEPTION в PL/pgSQL. Информация об ошибке доступна через специальные переменные, такие как SQLSTATE и SQLERRM.

DO $$
BEGIN
    PERFORM 1/0;
EXCEPTION WHEN OTHERS THEN
    RAISE NOTICE 'Error Code: %', SQLSTATE;
    RAISE NOTICE 'Error Message: %', SQLERRM;
END $$;

SQLite: Не имеет встроенной функции, аналогичной @@ERROR. Обычно проверяют результат последней операции через API (например, sqlite3_errcode() в C) или в некоторых обертках проверяют, вернула ли команда ошибку.

Типичные ошибки

Самая распространенная ошибка — проверка значения функции @@ERROR после нескольких операторов. Так как значение обнуляется после каждой выполненной инструкции, проверка будет отражать результат только последней из них.

INSERT INTO MyTable (Col1) VALUES (1);
PRINT 'Операция выполнена.'; -- Эта строка сбрасывает @@ERROR, если INSERT прошел успешно
IF @@ERROR <> 0
    PRINT 'Ошибка!'; -- Это сообщение не выведется, даже если INSERT завершился ошибкой

Решение — немедленная проверка или сохранение в переменную.

DECLARE @Err INT;
INSERT INTO MyTable (Col1) VALUES (1);
SET @Err = @@ERROR;
PRINT 'Операция выполнена.';
IF @Err <> 0
    PRINT 'Ошибка!';

Другая ошибка — попытка использовать @@ERROR в качестве возвращаемого значения пользовательской функции. Это невозможно, так как функция является системной и контекстно-зависимой.

История изменений

Функция @@ERROR присутствует в SQL Server с ранних версий. Ее поведение оставалось неизменным. Основное изменение в подходе к обработке ошибок произошло с выходом SQL Server 2005, где была введена конструкция TRY...CATCH. С этого момента использование TRY...CATCH стало рекомендованным методом, хотя @@ERROR сохранилась для обеспечения обратной совместимости и для сценариев, где необходима простая проверка без перехвата исключений.

Расширенные примеры

Использование в транзакции для принятия решения о commit или rollback. Это классический паттерн до появления TRY...CATCH.

Пример sql
BEGIN TRANSACTION;
DECLARE @ErrorOccurred INT = 0;

DELETE FROM Orders WHERE OrderID = 12345;
SET @ErrorOccurred = @@ERROR;

IF @ErrorOccurred = 0
BEGIN
    INSERT INTO AuditLog (Action) VALUES ('Order Deleted');
    SET @ErrorOccurred = @@ERROR;
END

IF @ErrorOccurred = 0
    COMMIT TRANSACTION;
ELSE
    ROLLBACK TRANSACTION;

SELECT @ErrorOccurred AS FinalErrorCode;

Совместное использование с другими системными функциями для получения деталей об ошибке.

Пример sql
BEGIN TRY
    SELECT 1/0;
END TRY
BEGIN CATCH
    -- Для обратной совместимости можно использовать внутри CATCH,
    -- но лучше применять ERROR_NUMBER()
    DECLARE @ErrNum INT = @@ERROR;
    SELECT
        @ErrNum AS ErrorCodeFromAtAtError,
        ERROR_NUMBER() AS ErrorCodeFromFunction,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH
ErrorCodeFromAtAtError ErrorCodeFromFunction ErrorMessage
---------------------- --------------------- -----------------------------------
8134                   8134                  Divide by zero error encountered.

Обработка ситуации, когда ошибка может быть не критичной, и ее код нужно проигнорировать.

Пример sql
-- Подавление конкретной ошибки (например, отсутствия объекта)
DROP TABLE #TempTable;
IF @@ERROR = 3701 -- Cannot drop the table '#TempTable', because it does not exist or you do not have permission.
    PRINT 'Временная таблица уже была удалена.';
ELSE IF @@ERROR <> 0
    PRINT 'Произошла другая ошибка.';

MS SQL @@ERROR function comments

En
@@ERROR Returns the error number for the last Transact-SQL statement executed