Sair de uma consulta em uma instrução de caso?

8

Estou tentando configurar uma consulta, para que ele compare duas datas de duas tabelas diferentes e, se forem iguais, a consulta será encerrada. Se eles não forem iguais, a consulta continuará e inserirá algumas coisas. Eu não consigo descobrir como fazê-lo fazer o que eu quero, no entanto.

SELECT TOP(1) @dateA=a.someDate
FROM a
ORDER BY DESC;
SELECT TOP(1) @dateB=b.someDate
FROM b
ORDER BY DESC;

CASE WHEN @dateA=@dateB THEN raiseerror('dates equal',20,-1) with log;

Insert statements;

Qualquer ajuda seria super apreciada.

thejoker34
fonte
Algumas outras variantes do SQL têm uma expressão e uma instrução denominadas CASE- SQL Server possui apenas a CASEexpressão.
RDFozz
3
Você realmente quer para elevar o erro? Ou isso é apenas uma tentativa de sair?
Kevin

Respostas:

16

CASE é uma expressão (não uma instrução) e não pode ser usada para controle de fluxo como esse - não para chamar comandos, não para retornar mais de uma coluna / valor, não para ser usado como um comando por si só.

Parece-me que você pode usar apenas IFpara aumentar o erro quando as datas são iguais; caso contrário, execute as inserções.

IF @dateA = @dateB 
BEGIN
  raiseerror('dates equal',20,-1) with log;
END
ELSE -- maybe you don't need a batch-aborting, logging error level
BEGIN
  INSERT ...
END

Você também pode fazer o contrário. Execute as inserções apenas se as datas não forem iguais ; caso contrário, aumente o erro:

IF @dateA <> @dateB
BEGIN
  INSERT ...
END
ELSE
BEGIN
  raiserror ...
END

Se você pensou em usar o erro apenas com o objetivo de deixar de executar as inserções, basta remover tudo da parte ELSEinferior, pois a única maneira de as inserções funcionarem é quando @dateAe não@dateB são iguais :

IF @dateA <> @dateB
BEGIN
  INSERT ...
END

Voltei a ser pedante sobre coisas como linhas (vs. "registros") e colunas (vs. "campos"), mas toda a expressão vs. declaração é uma distinção muito importante, exatamente por esse motivo. Consulte " Segredos sujos da expressão CASE ".

Aaron Bertrand
fonte
Principalmente uma boa resposta, exceto por um nitpick. O uso do operador '<>' não funciona bem com valores NULL. Se um dos seus valores de data for NULL, o operador 'não igual' retornará resultados inesperados. Tente este "SELECT CASE WHEN (1 <> NULL) THEN '! =' ELSE '==' END"
user5151179
11
@ user5151179 Tenho certeza de que Aaron sabe a diferença. Verifique também se o OP na pergunta diz o que ele quer fazer quando as duas datas são iguais e o que quando elas não são iguais. Ele não menciona o que eles querem fazer quando um ou os dois são NULL. Ainda é uma boa observação que as duas versões que Aaron fornece farão coisas diferentes nesse caso.
precisa saber é o seguinte
6

Use um em IFvez de umCASE

 IF @dateA=@dateB 
    raiseerror('dates equal',20,-1) with log;
 ELSE
    BEGIN
        Insert statements;
    END

Obviamente, isso pressupõe que você realmente deseja gerar um erro. A outra opção seria:

 IF @dateA<>@dateB 
    BEGIN
        Insert statements;
    END

Agora, observe oe BEGINo END. Isso vai ser importante. a IFdeclaração (e a ELSE) afeta apenas o comando logo abaixo dela. Se você precisar de mais de um comando, precisará de um BEGIN e um END .

Kenneth Fisher
fonte
2

Outras respostas apontaram que o CASE é uma expressão , não uma afirmação e, portanto, não pode, por si só, abranger afirmações (como RAISEERRORqualquer outra). Se as condições não forem muitas - principalmente quando é apenas uma condição -, a instrução SE é a escolha perfeita para o que você está tentando fazer, como também foi mencionado.

No entanto, dependendo do seu cenário, uma expressão CASE ainda pode ser usada, mas não exatamente da maneira que você mostrou. Em particular, se houver muitas condições a serem verificadas em que uma correspondência deve resultar no mesmo conjunto de ações (por exemplo, gerar uma exceção e encerrar o script), você poderá usar uma expressão CASE em uma instrução de atribuição que armazene o resultado do CASE e siga com um FI verificando o resultado armazenado e executando as ações necessárias, se apropriado, da seguinte maneira:

DECLARE @ErrorMessage varchar(1000);

SET @ErrorMessage =
  CASE WHEN @dateA = @dateB THEN
    'Dates equal'
  CASE WHEN ... /* some other condition */ THEN
    'Some other message'
  .
  .
  .
  ELSE
    ''  -- no message if nothing is wrong;
        -- you can also omit the ELSE branch entirely,
        -- which means the same as ELSE NULL
  END
;

IF @ErrorMessage <> ''
BEGIN
  RAISERROR (@ErrorMessage, 20, -1) WITH LOG;
END;

... /* continue the script */

Nesse caso, a ação necessária está gerando uma exceção, mas a mensagem retornada com a exceção precisa depender de qual condição foi verificada primeiro. A instrução de atribuição usa uma expressão CASE para escolher qual mensagem armazenar na @ErrorMessagevariável.

Você também pode ver que o erro é gerado apenas condicionalmente - somente se a variável realmente contiver uma mensagem para mostrar. Se o valor for uma sequência vazia ou nula, o script continuará sem interrupção.

Andriy M
fonte
0

Você precisa das variáveis?

declare @D1 table (dt date);
declare @D2 table (dt date);
insert into @D1 values ('2000-01-01'), ('2000-02-01');
insert into @D2 values ('2000-01-01'), ('2000-02-01');
if (select max(dt) from @D1) = (select max(dt) from @D2)
begin 
   select 'match'
end
else 
begin 
   select 'no match'
end
paparazzo
fonte