Pergunta

Eu tenho uma série de declarações T-SQL separadas pela palavra-chave de separador de lote do analisador de consulta especial:

GO

Se um lote falhar, preciso do analisador de consultas para não experimentar lotes subsequentes - quero que ele pare de processar a série de lotes.

Por exemplo:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go

PRINT 'This should not run'
go

Resultado:

This runs
Server: Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
This should not run

Possível?


Atualizar

Um exemplo disso em uso real pode ser:

 sp_rename 'Shelby', 'Kirsten'
 go

 DROP VIEW PeekAView
 go

 CREATE VIEW PeekAViewAS 
 SELECT * FROM Kirsten
 go
Foi útil?

Solução

Aqui está como eu faria isso:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go
if (@@error <> 0)
    Begin
    set nocount on
    set noexec on
    End
GO

PRINT 'This should not run'
go

set noexec off
set nocount off
GO

O modo "NoEXEC" coloca o SSMS é um estado em que apenas compila o T-SQL e na verdade não o executa. É semelhante a pressionar acidentalmente o botão da barra de ferramentas de parse (Ctrl+F5) em vez de executar (F5).

Não se esqueça de desligar o Noexec no final do seu script. Caso contrário, os usuários ficarão confusos com os "comando (s) permanente (s) concluídos com êxito". mensagens.

Eu uso a verificação contra o erro @@ no lote subsequente, em vez de usar os blocos Try Catch. Usando o erro @@ no próximo lote, capturará erros de compilação, como "a tabela não existe".

Além do modo NOEXEC, também alterno o modo Nocount. Com o modo NoEXEC ON e NOCOUNT OFF, suas consultas ainda relatarão uma mensagem "(0 linhas (s) afetadas)". A mensagem sempre relata zero linhas, porque você está no modo NoExec. No entanto, transformar o Nocount em suprime essas mensagens.

Observe também que, se a execução do SQL Server 2005, o comando que você está pulando ainda poderá fornecer mensagens de erro se referir uma tabela que não existir e o comando se o primeiro comando no lote. Forçar o comando a ser o segundo comando no lote com uma declaração de impressão falsa pode suprimir isso. Ver MS Bug #569263 para mais detalhes.

Outras dicas

Você pode ativar a opção de menu "consulta, modo sqlcmd" e colocar o seguinte no início do script:

:on error exit

Isso interromperá a execução quando ocorrer um erro, mesmo que haja lotes subsequentes.

Apenas certifique -se de não executar acidentalmente o script sem o modo SQLCMD, porque você obterá o comportamento típico em que os erros são ignorados.

Quando preciso fazer isso, emite um Raiserror da gravidade 20. Isso, ou superior, matará a conexão atual e impedirá a execução de "lotes" subsequentes. Sim, pode ser estranho, mas faz o trabalho.

Criar uma tabela temporária; e atualize -o após cada etapa (se for bem -sucedido); e, em seguida, verifique o sucesso da etapa anterior, validando contra a tabela.

create table #ScriptChecker (SuccessfullStep int)

-- Do Step One
Insert into #ScriptChecker
Select 1

-- Step 2
If exists (select * from #ScriptChecker where SuccessfullStep = 1)
-- Do Step 2 ...

Baseado na ideia @u07ch, mas apenas insira o fracasso ...

create table #test (failure  int)

if not exists (select * from #test)
BEGIN
    print 'one' --sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'two'--sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'three' ---SQL SERVER 2000 version
    --error--
    SELECT 0/0, 'This causes an error'
    IF @@ERROR!=0
    BEGIN
        insert into #test values (1)
        PRINT 'ERROR'
    END
end 
go

if not exists (select * from #test)
BEGIN
    print 'three'  ---SQL SERVER 2005/2008 version
    BEGIN TRY
    --error--
        SELECT 0/0, 'This causes an error'
    END TRY
    BEGIN CATCH
        insert into #test values (1)
        PRINT 'ERROR'
    END CATCH
END
go

if not exists (select * from #test)
BEGIN
    --sql here
    print 'four'
END
go

Saída 2000:

one
two
three

----------- --------------------
Msg 8134, Level 16, State 1, Line 7
Divide by zero error encountered.

(1 row(s) affected)

ERROR

Saída 2005/2008:

one
two
three

----------- --------------------

(0 row(s) affected)

(1 row(s) affected)

ERROR

Erland Sommarskog no Microsoft.public.sqlserver.programing Group teve uma boa ideia:

Em um script de mudança como o que você postou, você precisa estar na defensiva e iniciar cada lote com se @@ trancount> 0.

Usando

IF @@trancount > 0 

é muito mais limpo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top