SQL Server-остановить или прервать выполнение сценария SQL
есть ли способ немедленно остановить выполнение сценария SQL в SQL server, например, команду" break "или" exit"?
У меня есть скрипт, который выполняет некоторую проверку и поиск, прежде чем он начнет делать вставки, и я хочу, чтобы он остановился, если какая-либо из проверок или поисков не удастся.
18 ответов:
The 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 ' не является напечатанный.
предостережения:
- это работает только если вы вошли в систему как администратор ('sysadmin' роль), а также оставляет вас без подключения к базе данных.
- если вы не вошли в систему как администратор, вызов RAISEERROR () сам по себе завершится ошибкой и скрипт продолжит выполнение.
- при вызове с помощью программы sqlcmd.exe, код выхода 2745 будет сообщен.
метод 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 Managment Studio проносится мимо даже ошибок времени разбора! Тем не менее, если вы запускаете их из командной строки, это нормально.
Я бы не использовал 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
даже если ваша проверка является более сложным, вы должны только нужно несколько переменных флага, чтобы включить в вашу окончательную проверку(ы).
вы можете обернуть свой оператор 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
Я успешно расширил решение noexec on/off с помощью транзакции, чтобы запустить скрипт полностью или ничего.
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 в IF, даже если произошла ошибка и выполнение было отключено. Однако значение равно 1 только в том случае, если выполнение не было отключено. Следовательно, я могу красиво зафиксировать или откатить транзакцию соответственно.
в SQL 2012+, Вы можете использовать бросить.
THROW 51000, 'Stopping execution because validation failed.', 0; PRINT 'Still Executing'; -- This doesn't execute with THROW
от MSDN:
вызывает исключение и передает выполнение блоку CATCH конструкции TRY...CATCH... Если конструкция TRY ... CATCH недоступна, сеанс завершается. Задаются номер строки и процедура, в которой возникает исключение. Серьезность установлена на 16.
Это хранимая процедура? Если это так, я думаю, что вы могли бы просто сделать возврат, например "Return NULL";
далее уточните метод 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-------------
Я бы предложил вам обернуть соответствующий блок кода в блок try catch. Затем вы можете использовать событие Raiserror со степенью серьезности 11, чтобы разбиться на блок catch, если хотите. Если вы просто хотите поднять ошибки, но продолжить выполнение в блоке try, используйте более низкую степень серьезности.
смысл?
Ура, Джон
[отредактировано для включения BOL Ссылка]
http://msdn.microsoft.com/en-us/library/ms175976 (SQL. 90). aspx
можно использовать RAISERROR.
вы можете изменить поток выполнения с помощью перейти отчетность:
IF @ValidationResult = 0 BEGIN PRINT 'Validation fault.' GOTO EndScript END /* our code */ EndScript:
ни одна из этих работ с утверждениями "GO". В этом коде, независимо от того, является ли серьезность 10 или 11, вы получаете окончательный оператор печати.
Тестовый Скрипт:
-- ================================= 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 ...
.)
Это было мое решение:
...
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
оператор в противном случае скрипт продолжается без ошибок! (hense raiserror не является "throwerror"; -)) и, конечно, делает откат, если это необходимо!
raiserror()
приятно сказать человеку, который выполняет скрипт, что что-то пошло не так.
Если вы просто выполняете скрипт в Management Studio и хотите остановить выполнение или откат транзакции (если используется) при первой ошибке, то лучший способ, который я считаю, - использовать блок try catch (SQL 2005 и далее). Это хорошо работает в среде Management studio при выполнении файла сценария. Хранимой процедуре всегда можете использовать его в качестве хорошо.