Відповіді:
RAISERROR метод
raiserror('Oh no a fatal error', 20, -1) with log
Це припинить з'єднання, тим самим зупиняючи роботу решти сценарію.
Зауважте, що і рівень тяжкості 20 або вище, і WITH LOG
варіант необхідні, щоб він працював таким чином.
Це навіть працює з заявами GO, наприклад.
print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'
Дасть вам вихід:
hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
Зауважте, що "ho" не друкується.
ПЕРЕМОГИ:
Метод noexec
Інший метод, який працює з GO твердженнями, це set noexec on
. Це спричиняє пропуск решти сценарію. Це з'єднання не припиняється, але його потрібно noexec
вимкнути ще раз, перш ніж виконуватимуться будь-які команди.
Приклад:
print 'hi'
go
print 'Fatal error, script will not continue!'
set noexec on
print 'ho'
go
-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able
-- to run this script again in the same session.
Просто використовуйте ПОВЕРНЕННЯ (воно буде працювати як всередині, так і зовні збереженої процедури).
Якщо ви можете користуватися режимом SQLCMD, тоді заповідник
:on error exit
(Включаючи двокрапки) призведе до того, що RAISERROR фактично зупинить сценарій. Наприклад,
:on error exit
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U'))
RaisError ('This is not a Valid Instance Database', 15, 10)
GO
print 'Keep Working'
виведе:
Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.
і партія зупиниться. Якщо режим SQLCMD не увімкнено, ви отримаєте помилку розбору щодо двокрапки. На жаль, це не зовсім куленебезпечно, ніби сценарій запускається, не перебуваючи в режимі SQLCMD, студія управління SQL проходить через повний навіть час розбору помилок! Але якщо ви запускаєте їх з командного рядка, це добре.
Я б не використовував RAISERROR- SQL має IF заяви, які можна використовувати для цієї мети. Зробіть валідацію та пошук і встановіть локальні змінні, а потім використовуйте значення змінних у операторах IF, щоб зробити умовні вставки.
Вам не потрібно перевіряти змінний результат кожного тесту перевірки. Зазвичай ви можете зробити це лише однією змінною прапорця, щоб підтвердити всі умови, що пройшли:
declare @valid bit
set @valid = 1
if -- Condition(s)
begin
print 'Condition(s) failed.'
set @valid = 0
end
-- Additional validation with similar structure
-- Final check that validation passed
if @valid = 1
begin
print 'Validation succeeded.'
-- Do work
end
Навіть якщо ваша перевірка є більш складною, вам знадобиться лише кілька змінних прапорців, які потрібно включити до остаточної перевірки.
RAISERROR
, особливо якщо ви не знаєте, хто буде запускати сценарії та які привілеї.
declare @i int = 0; if @i=0 begin select '1st stmt in IF block' go end else begin select 'ELSE here' end go
У SQL 2012+ ви можете використовувати THROW .
THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW
Від MSDN:
Підвищує виняток і передає виконання блоку CATCH конструкції TRY… CATCH… Якщо конструкція TRY… CATCH недоступна, сеанс закінчується. Встановлюється номер рядка та порядок, коли піднято виняток. Суворість встановлюється 16.
Я успішно розширив рішення для включення / вимкнення noexec транзакцією для запуску сценарію повністю або нічого.
set noexec off
begin transaction
go
<First batch, do something here>
go
if @@error != 0 set noexec on;
<Second batch, do something here>
go
if @@error != 0 set noexec on;
<... etc>
declare @finished bit;
set @finished = 1;
SET noexec off;
IF @finished = 1
BEGIN
PRINT 'Committing changes'
COMMIT TRANSACTION
END
ELSE
BEGIN
PRINT 'Errors occured. Rolling back changes'
ROLLBACK TRANSACTION
END
Мабуть, компілятор "розуміє" змінну @finished в ІФ, навіть якщо сталася помилка і виконання було відключено. Однак значення встановлюється на 1, лише якщо виконання не було вимкнено. Отже, я можу відповідним чином здійснити або повернути транзакцію відповідно.
IF (XACT_STATE()) <> 1 BEGIN Set NOCOUNT OFF ;THROW 525600, 'Rolling back transaction.', 1 ROLLBACK TRANSACTION; set noexec on END;
Але виконання ніколи не припинялося, і я закінчився трьома помилками "Відхилення трансакції". Будь-які ідеї?
ви можете обернути свій оператор SQL в циклі WHILE і використовувати BREAK, якщо потрібно
WHILE 1 = 1
BEGIN
-- Do work here
-- If you need to stop execution then use a BREAK
BREAK; --Make sure to have this break at the end to prevent infinite loop
END
DECLARE @ST INT; SET @ST = 1; WHILE @ST = 1; BEGIN; SET @ST = 0; ...; END
Більш докладно, але чорт, це все одно TSQL ;-)
Ви можете змінити потік виконання за допомогою операторів GOTO :
IF @ValidationResult = 0
BEGIN
PRINT 'Validation fault.'
GOTO EndScript
END
/* our code */
EndScript:
Далі метод згущаються Sglasses, вищевказані лінії примусово використовувати режим SQLCMD, і або treminates scirpt , якщо не використовується режим SQLCMD або використовує , :on error exit
щоб вийти на якийсь - або помилки
CONTEXT_INFO використовується для відстеження стану.
SET CONTEXT_INFO 0x1 --Just to make sure everything's ok
GO
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2
BEGIN
SELECT CONTEXT_INFO()
SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT
WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO
----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------
Це збережена процедура? Якщо так, я думаю, що ви могли просто зробити повернення, наприклад, "Return NULL";
Я б запропонував вам загорнути відповідний код коду у блок спробувати. Потім ви можете використовувати подію Raiserror з різкістю 11, щоб перейти до блоку спіймання, якщо бажаєте. Якщо ви просто хочете зробити рейнджерс, але продовжуєте виконання у блоці спробу, тоді використовуйте меншу суворість.
Мати сенс?
Ура, Джон
[Відредаговано, щоб включити довідку про BOL]
http://msdn.microsoft.com/en-us/library/ms175976(SQL.90).aspx
ви можете використовувати RAISERROR .
Жоден з цих не працює із заявами "GO". У цьому коді, незалежно від того, ступінь тяжкості становить 10 чи 11, ви отримуєте остаточне твердження PRINT.
Тестовий сценарій:
-- =================================
PRINT 'Start Test 1 - RAISERROR'
IF 1 = 1 BEGIN
RAISERROR('Error 1, level 11', 11, 1)
RETURN
END
IF 1 = 1 BEGIN
RAISERROR('Error 2, level 11', 11, 1)
RETURN
END
GO
PRINT 'Test 1 - After GO'
GO
-- =================================
PRINT 'Start Test 2 - Try/Catch'
BEGIN TRY
SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage
RAISERROR('Error in TRY, level 11', 11, 1)
RETURN
END CATCH
GO
PRINT 'Test 2 - After GO'
GO
Результати:
Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
CauseError
-----------
ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.
Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO
Єдиний спосіб зробити цю роботу - написати сценарій без GO
заяв. Іноді це легко. Іноді це досить складно. (Використовуйте щось подібне IF @error <> 0 BEGIN ...
.)
Я RETURN
тут весь час використовую, працює в сценарії абоStored Procedure
Переконайтеся, що ви ROLLBACK
здійснили транзакцію, якщо ви перебуваєте в одній, інакше RETURN
негайно призведе до відкритої несхваленої транзакції
Це було моє рішення:
...
BEGIN
raiserror('Invalid database', 15, 10)
rollback transaction
return
END
Ви можете використовувати операцію GOTO. Спробуйте це. Це використання для вас повне.
WHILE(@N <= @Count)
BEGIN
GOTO FinalStateMent;
END
FinalStatement:
Select @CoumnName from TableName
Thx для відповіді!
raiserror()
працює добре, але ви не повинні забувати return
твердження, інакше сценарій продовжується без помилок! (отже, підйомник не є "меценатом" ;-)) і, звичайно, робити відкат, якщо потрібно!
raiserror()
приємно сказати людині, яка виконує сценарій, що щось пішло не так.
Якщо ви просто виконуєте скрипт у програмі Management Studio і хочете зупинити виконання або відкат транзакції (якщо використовується) при першій помилці, то найкращим способом, на який я вважаю, є використання блоку спробувати catch (SQL 2005 і далі). Це добре працює в студії менеджменту, якщо ви виконуєте файл сценарію. Збережений Proc завжди може використовувати це також.