Uscire da una query in un'istruzione case?


8

Sto cercando di impostare una query, in modo che confronterà due date da due diverse tabelle e, se sono uguali, la query verrà chiusa. Se non sono uguali, la query continuerà e inserirà alcune cose. Non riesco a capire come farlo per fare quello che voglio comunque.

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;

Qualsiasi aiuto sarebbe molto apprezzato.


Alcune altre varianti di SQL hanno sia un'espressione che un'istruzione denominata CASE- SQL Server ha solo l' CASEespressione.
RDFozz

3
Si fa realmente desidera per aumentare l'errore? O è solo un tentativo di uscire?
Kevin,

Risposte:


16

CASE è un'espressione (non un'istruzione) e non può essere utilizzata per il controllo del flusso in questo modo - per non chiamare comandi, per non restituire più di una colonna / valore, per non essere utilizzata come comando da sola.

Mi sembra che puoi semplicemente usare IFper aumentare l'errore quando le date sono uguali, altrimenti esegui gli inserti.

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

Potresti farlo anche nell'altro modo. Esegui gli inserti solo se le date non sono uguali , altrimenti genera l'errore:

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

Se hai pensato di utilizzare l'errore solo allo scopo di uscire dall'esecuzione degli inserti, puoi semplicemente rimuovere tutto dal ELSEbasso, poiché l'unico modo in cui verranno eseguiti gli inserti è quando @dateAe non@dateB sono uguali :

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

Ho ridimensionato il fatto di essere pedante su cose come le righe (rispetto ai "record") e le colonne (rispetto ai "campi"), ma l'intera cosa espressione vs. istruzione è una distinzione molto importante, proprio per questo motivo. Vedi " Segreti sporchi dell'espressione CASE ".


Soprattutto una buona risposta, ad eccezione di un nitpick. L'uso dell'operatore '<>' non gioca bene con i valori NULL. Se uno dei valori della data è NULL, l'operatore "non uguale" restituirà risultati imprevisti. Prova questo "SELEZIONA CASO QUANDO (1 <> NULL) THEN '! =' ELSE '==' END"
user5151179

1
@ user5151179 Sono abbastanza sicuro che Aaron conosca la differenza. Controlla anche che l'OP nella domanda dica cosa vuole fare quando le due date sono uguali e cosa quando non sono uguali. Non menziona affatto quello che vogliono fare quando uno o entrambi NULL. È comunque una buona osservazione che le due versioni fornite da Aaron faranno cose diverse in quel caso.
ypercubeᵀᴹ

6

Usa un IFinvece di aCASE

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

Questo ovviamente presuppone che tu voglia effettivamente sollevare un errore. L'altra opzione sarebbe:

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

Ora, nota il BEGINe il END. Saranno importanti. l' IFistruzione (e il ELSE) influenza solo il comando proprio sotto di essa. Se hai bisogno di più di un comando hai bisogno di BEGIN e END .


2

Altre risposte hanno sottolineato che CASE è un'espressione , non un'affermazione, e quindi non può di per sé racchiudere le dichiarazioni (come RAISEERRORo qualsiasi altra). Se le condizioni non sono molte, in particolare quando si tratta di una sola condizione, l'istruzione IF è la scelta perfetta per ciò che si sta tentando di fare, come è stato anche menzionato.

Tuttavia, a seconda del tuo scenario, è ancora possibile utilizzare un'espressione CASE, non esattamente come mostrato. In particolare, se ci sono molte condizioni da verificare in cui una corrispondenza dovrebbe comportare lo stesso insieme di azioni (ad esempio, sollevare un'eccezione e terminare lo script), è possibile utilizzare un'espressione CASE in un'istruzione di assegnazione che memorizza il risultato del CASE, quindi seguire con un IF che controlla il risultato memorizzato ed esegue le azioni richieste, se del caso, in questo modo:

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

In questo caso, l'azione necessaria genera un'eccezione, ma il messaggio restituito con l'eccezione deve dipendere dalla condizione verificata per prima. L'istruzione di assegnazione utilizza un'espressione CASE per scegliere quale messaggio archiviare nella @ErrorMessagevariabile.

Puoi anche vedere che l'errore viene generato solo in modo condizionale, solo se la variabile contiene effettivamente un messaggio da mostrare. Se il valore è una stringa vuota o nulla, lo script continuerà senza interruzioni.


0

Hai bisogno delle variabili?

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.