@@ERROR: примеры (SQL)
@@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.
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;Совместное использование с другими системными функциями для получения деталей об ошибке.
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 CATCHErrorCodeFromAtAtError ErrorCodeFromFunction ErrorMessage ---------------------- --------------------- ----------------------------------- 8134 8134 Divide by zero error encountered.
Обработка ситуации, когда ошибка может быть не критичной, и ее код нужно проигнорировать.
-- Подавление конкретной ошибки (например, отсутствия объекта)
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 'Произошла другая ошибка.';