it-swarm.com.de

Eine Abfrage in einer case-Anweisung beenden?

Ich versuche, eine Abfrage so einzurichten, dass zwei Daten aus zwei verschiedenen Tabellen verglichen werden. Wenn sie gleich sind, wird die Abfrage beendet. Wenn sie nicht gleich sind, wird die Abfrage fortgesetzt und einige Elemente eingefügt. Ich kann jedoch nicht herausfinden, wie ich es dazu bringen kann, das zu tun, was ich will.

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

CASE WHEN @[email protected] THEN raiseerror('dates equal',20,-1) with log;

Insert statements;

Jede Hilfe wäre super dankbar.

8
thejoker34

CASE ist ein Ausdruck (keine Anweisung) und kann nicht für eine solche Flusskontrolle verwendet werden - keine Befehle aufrufen, nicht mehr als eine Spalte/einen Wert zurückgeben, nicht als Befehl für verwendet werden seine eigene.

Mir scheint, Sie können einfach IF verwenden, um den Fehler auszulösen, wenn die Daten gleich sind. Andernfalls führen Sie die Einfügungen aus.

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

Sie können es auch anders machen. Führen Sie die Einfügungen nur aus, wenn die Daten nicht gleich sind , andernfalls wird der Fehler ausgelöst:

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

Wenn Sie daran gedacht haben, den Fehler nur zu verwenden, um die Ausführung der Einfügungen zu beenden, können Sie einfach alles aus ELSE down entfernen, da dies nur der Fall ist run ist wenn @dateA und @dateB sind ungleich :

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

Ich bin weit zurückgegangen, weil ich in Bezug auf Zeilen (vs. "Datensätze") und Spalten (vs. "Felder") pedantisch war, aber genau aus diesem Grund ist der gesamte Ausdruck vs. Aussage eine sehr wichtige Unterscheidung. Siehe " Schmutzige Geheimnisse des CASE-Ausdrucks ."

16
Aaron Bertrand

Verwenden Sie ein IF anstelle eines CASE

 IF @[email protected] 
    raiseerror('dates equal',20,-1) with log;
 ELSE
    BEGIN
        Insert statements;
    END

Dies setzt natürlich voraus, dass Sie tatsächlich einen Fehler auslösen möchten. Die andere Option wäre:

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

Beachten Sie nun das BEGIN und das END. Die werden wichtig sein. Die Anweisung IF (und die Anweisung ELSE) wirken sich nur auf den Befehl direkt darunter aus. Wenn Sie mehr als einen Befehl benötigen, benötigen Sie ein BEGIN und ein END .

6
Kenneth Fisher

Andere Antworten haben darauf hingewiesen, dass CASE ein Ausdruck ist, keine Anweisung, und daher selbst nicht Anweisungen (wie RAISEERROR oder andere) umfassen kann. Wenn es nicht viele Bedingungen gibt - insbesondere wenn es sich nur um eine Bedingung handelt -, ist die IF-Anweisung die perfekte Wahl für das, was Sie versuchen, wie bereits erwähnt.

Abhängig von Ihrem Szenario kann dennoch ein CASE-Ausdruck verwendet werden, nur nicht genau so, wie Sie es gezeigt haben. Insbesondere wenn viele Bedingungen überprüft werden müssen, unter denen eine Übereinstimmung zu denselben Aktionen führen sollte (z. B. Auslösen einer Ausnahme und Beenden des Skripts), können Sie einen CASE-Ausdruck in einer Zuweisungsanweisung verwenden, in der das CASE-Ergebnis gespeichert ist, und dann folgen es mit einer IF, die das gespeicherte Ergebnis überprüft und gegebenenfalls die erforderlichen Aktionen ausführt, wie folgt:

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 diesem Fall löst die erforderliche Aktion eine Ausnahme aus, aber die mit der Ausnahme zurückgegebene Nachricht muss davon abhängen, welche Bedingung zuerst überprüft wurde. Die Zuweisungsanweisung verwendet einen CASE-Ausdruck, um auszuwählen, welche Nachricht in der Variablen @ErrorMessage Gespeichert werden soll.

Sie können auch sehen, dass der Fehler nur bedingt ausgelöst wird - nur wenn die Variable tatsächlich eine anzuzeigende Nachricht enthält. Wenn der Wert eine leere Zeichenfolge oder eine Null ist, wird das Skript ohne Unterbrechung fortgesetzt.

2
Andriy M

Benötigen Sie die Variablen?

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
0
paparazzo