Команда T-SQL STOP или ABORT в SQL Server
есть ли команда в Microsoft SQL Server T-SQL, чтобы сообщить скрипту остановить обработку? У меня есть скрипт, который я хочу сохранить для архивных целей, но я не хочу, чтобы запустить его.
9 ответов
альтернативным решением может быть изменение потока выполнения вашего скрипта с помощью GOTO
заявление...
DECLARE @RunScript bit;
SET @RunScript = 0;
IF @RunScript != 1
BEGIN
RAISERROR ('Raise Error does not stop processing, so we will call GOTO to skip over the script', 1, 1);
GOTO Skipper -- This will skip over the script and go to Skipper
END
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
Skipper: -- Don't do nuttin!
предупреждение! Вышеприведенный образец был получен из примера, который я получил от Меррилла Олдрича. Прежде чем реализовать GOTO
заявление вслепую, я рекомендую вам прочитать его учебник о управление потоком в скриптах T-SQL.
нет, нет-у вас есть несколько вариантов:
оберните весь скрипт в большой блок if / end, который просто гарантирован, чтобы не быть истинным (т. е. "если 1=2 begin" - это будет работать только в том случае, если скрипт не включает никаких операторов GO (как те указывают на новый пакет)
Используйте оператор return вверху (опять же, ограниченный разделителями пакетов)
используйте подход на основе соединения, который будет убедитесь, что не выполняется для всего скрипта (все соединение, чтобы быть более точным) - используйте что-то вроде 'УСТАНОВИТЬ PARSEONLY ON' или 'УСТАНОВИТЬ NOEXEC НА' в верхней части скрипта. Это гарантирует, что все операторы в соединении (или пока указанный оператор set не выключен) не будут выполняться и вместо этого будут проанализированы/скомпилированы только.
используйте блок комментариев, чтобы прокомментировать весь скрипт (т. е. / * И */)
EDIT: демонстрация того, что инструкция "return" является пакетной-обратите внимание, что вы будете продолжать видеть результирующие наборы после возвращения:
select 1
return
go
select 2
return
select 3
go
select 4
return
select 5
select 6
go
чтобы обойти проблему возврата / GO, вы можете поставить RAISERROR ('Oi! Stop!', 20, 1) WITH LOG
в верхней части.
это закроет клиентское соединение согласно RAISERROR на MSDN.
очень большой недостаток-надо быть сисадмином, чтобы использовать тяжести 20.
Edit:
простая демонстрация, чтобы противостоять комментарию Джерси-чувака...
RAISERROR ('Oi! Stop!', 20, 1) WITH LOG
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
RAISERROR с серьезностью 20 сообщит об ошибке в средстве просмотра событий.
вы можете использовать SET PARSEONLY ON; (или NOEXEC). В конце скрипта используйте GO SET PARSEONLY OFF;
SET PARSEONLY ON;
-- statement between here will not run
SELECT 'THIS WILL NOT EXEC';
GO
-- statement below here will run
SET PARSEONLY OFF;
попробуйте запустить это как сценарий TSQL
SELECT 1
RETURN
SELECT 2
SELECT 3
возврат завершает выполнение.
безусловный выход из запроса или процедура. Возвращение немедленно и полный и может быть использовано в любой момент для выхода из процедуры, пакета или блок операторов. Заявления, которые последующие возвраты не выполняются.
несмотря на его очень явное и сильное описание, RETURN не работал для меня внутри хранимой процедуры (чтобы пропустить дальнейшее выполнение). Мне пришлось изменить логику условий. Происходит на обоих SQL 2008, 2008 R2:
create proc dbo.prSess_Ins
(
@sSessID varchar( 32 )
, @idSess int out
)
as
begin
set nocount on
select @id= idSess
from tbSess
where sSessID = @sSessID
if @idSess > 0 return -- exit sproc here
begin tran
insert tbSess ( sSessID ) values ( @sSessID )
select @idSess= scope_identity( )
commit
end
пришлось изменить на:
if @idSess is null
begin
begin tran
insert tbSess ( sSessID ) values ( @sSessID )
select @idSess= scope_identity( )
commit
end
обнаружен в результате нахождения дублированных строк. Отладка отпечатков подтвердила, что значение @idSess было больше нуля в if check-RETURN не нарушило выполнение!
вот несколько kludgy способ сделать это, который работает с GO-пакетами, используя "глобальную" переменную.
if object_id('tempdb..#vars') is not null
begin
drop table #vars
end
create table #vars (continueScript bit)
set nocount on
insert #vars values (1)
set nocount off
-- Start of first batch
if ((select continueScript from #vars)=1) begin
print '1'
-- Conditionally terminate entire script
if (1=1) begin
set nocount on
update #vars set continueScript=0
set nocount off
return
end
end
go
-- Start of second batch
if ((select continueScript from #vars)=1) begin
print '2'
end
go
и вот та же идея, используемая с транзакцией и блоком try/catch для каждой GO-партии. Вы можете попытаться изменить различные условия и / или позволить ему генерировать ошибку (разделить на 0, см. комментарии), чтобы проверить, как он ведет себя:
if object_id('tempdb..#vars') is not null
begin
drop table #vars
end
create table #vars (continueScript bit)
set nocount on
insert #vars values (1)
set nocount off
begin transaction;
-- Batch 1 starts here
if ((select continueScript from #vars)=1) begin
begin try
print 'batch 1 starts'
if (1=0) begin
print 'Script is terminating because of special condition 1.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
print 'batch 1 in the middle of its progress'
if (1=0) begin
print 'Script is terminating because of special condition 2.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
set nocount on
-- use 1/0 to generate an exception here
select 1/1 as test
set nocount off
end try
begin catch
set nocount on
select
error_number() as errornumber
,error_severity() as errorseverity
,error_state() as errorstate
,error_procedure() as errorprocedure
,error_line() as errorline
,error_message() as errormessage;
print 'Script is terminating because of error.'
update #vars set continueScript=0
set nocount off
return
end catch;
end
go
-- Batch 2 starts here
if ((select continueScript from #vars)=1) begin
begin try
print 'batch 2 starts'
if (1=0) begin
print 'Script is terminating because of special condition 1.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
print 'batch 2 in the middle of its progress'
if (1=0) begin
print 'Script is terminating because of special condition 2.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
set nocount on
-- use 1/0 to generate an exception here
select 1/1 as test
set nocount off
end try
begin catch
set nocount on
select
error_number() as errornumber
,error_severity() as errorseverity
,error_state() as errorstate
,error_procedure() as errorprocedure
,error_line() as errorline
,error_message() as errormessage;
print 'Script is terminating because of error.'
update #vars set continueScript=0
set nocount off
return
end catch;
end
go
if @@trancount > 0 begin
if ((select continueScript from #vars)=1) begin
commit transaction
print 'transaction committed'
end else begin
rollback transaction;
print 'transaction rolled back'
end
end
Я знаю, что вопрос старый и получил правильный ответ несколькими различными способами, но нет ответа, как мой, который я использовал в подобных ситуациях. Первый подход (очень простой):
IF (1=0)
BEGIN
PRINT 'it will not go there'
-- your script here
END
PRINT 'but it will here'
второй подход:
PRINT 'stop here'
RETURN
-- your script here
PRINT 'it will not go there'
Вы можете легко проверить это самостоятельно, чтобы убедиться, что он ведет себя, как ожидалось.