¿Salir de una consulta en una declaración de caso?

8

Estoy tratando de configurar una consulta, para que compare dos fechas de dos tablas diferentes, y si son iguales, entonces la consulta se cierra. Si no son iguales, la consulta continuará e insertará algunas cosas. Sin embargo, no puedo entender cómo hacer que haga lo que quiero.

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;

Cualquier ayuda sería muy apreciada.

thejoker34
fuente
Algunas otras variantes de SQL tienen una expresión y una instrucción denominada CASE: SQL Server solo tiene la CASEexpresión.
RDFozz
3
¿Realmente quieres plantear el error? ¿O es solo un intento de salir?
Kevin

Respuestas:

16

CASE es una expresión (no una declaración) y no se puede usar para un control de flujo como ese, no para llamar a comandos, no para devolver más de una columna / valor, no para ser usado como un comando por sí solo.

Me parece que solo puede usar IFpara aumentar el error cuando las fechas son iguales, de lo contrario, ejecute las inserciones.

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

También puedes hacerlo de otra manera. Ejecute las inserciones solo si las fechas no son iguales , de lo contrario, genere el error:

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

Si pensó utilizar el error solo con el fin de dejar de ejecutar las inserciones, puede eliminar todo de ELSEabajo, ya que la única forma en que se ejecutarán las inserciones es cuándo @dateAy no@dateB son iguales :

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

He retrocedido mucho para ser pedante sobre cosas como filas (vs. "registros") y columnas (vs. "campos"), pero la expresión completa vs. declaración es una distinción muy importante, exactamente por esta razón. Ver " Secretos sucios de la expresión CASE ".

Aaron Bertrand
fuente
En general, es una buena respuesta, excepto por un punto. El uso del operador '<>' no funciona bien con valores NULL. Si uno de sus valores de fecha es NULL, el operador 'no igual' devolverá resultados inesperados. Pruebe esto "SELECCIONE EL CASO CUANDO (1 <> NULL) LUEGO '! =' ELSE '==' END"
user5151179
1
@ user5151179 Estoy bastante seguro de que Aaron sabe la diferencia. También verifique que el OP en la pregunta dice qué quiere hacer cuando las dos fechas son iguales y cuándo no lo son. No menciona en absoluto lo que quieren hacer cuando uno o ambos lo están NULL. Todavía es una buena observación que las dos versiones que ofrece Aaron harán cosas diferentes en ese caso.
ypercubeᵀᴹ
6

Use un en IFlugar de unCASE

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

Por supuesto, esto supone que realmente desea generar un error. La otra opción sería:

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

Ahora, tenga en cuenta el BEGINy el END. Esos serán importantes. la IFdeclaración (y la ELSE) solo afecta el comando justo debajo de ella. Si necesita más de un comando, necesita un COMIENZO y un FIN .

Kenneth Fisher
fuente
2

Otras respuestas han señalado que CASE es una expresión , no una declaración, y por lo tanto no puede abarcar declaraciones (como RAISEERRORo cualquier otra). Si las condiciones no son muchas, particularmente cuando es solo una condición, la declaración IF es la elección perfecta para lo que está tratando de hacer, como también se ha mencionado.

Sin embargo, dependiendo de su escenario, una expresión CASE aún podría usarse, pero no exactamente de la manera que ha mostrado. En particular, si hay muchas condiciones para verificar donde una coincidencia debe dar como resultado el mismo conjunto de acciones (por ejemplo, generar una excepción y finalizar el script), puede usar una expresión CASE en una declaración de asignación que almacene el resultado de CASE, luego siga con un IF que verifica el resultado almacenado y realiza las acciones requeridas, si corresponde, de esta manera:

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 */

En este caso, la acción necesaria genera una excepción, pero el mensaje devuelto con la excepción debe depender de qué condición se verificó primero. La instrucción de asignación usa una expresión CASE para elegir qué mensaje almacenar en la @ErrorMessagevariable.

También puede ver que el error se genera solo condicionalmente, solo si la variable realmente contiene un mensaje para mostrar. Si el valor es una cadena vacía o nula, el script simplemente continuará sin interrupción.

Andriy M
fuente
0

¿Necesitas las variables?

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
fuente