2017-05-16 8 views
1

Unten ist mein Versuch, eine CASE STATEMENT in eine WHERE Klausel aufzunehmen, es funktioniert nicht. Weiß jemand wie ich das korrigieren kann?Oracle mit CASE-Anweisung in WHERE-Klausel

Ich kann nicht scheinen, die Beispiele, die ich schon gesehen habe, Sinn zu machen. Hier ist ein weiterer Versuch, ohne eine CASE-Anweisung gibt aber kein Ergebnis:

SELECT 
    e.ColumnName 
FROM 
    Schema.TableName e 
WHERE 
    (pEntityName IS NULL AND e.ColumnName != '') OR 
    (pEntityName IS NOT NULL AND e.ColumnName = pEntityName); 

Wie auch immer, hier ist die wahre Probe-Abfrage, die kein Ergebnis zurückgibt: enter image description here

Und dann ist hier die Tabelle mit Daten: enter image description here Dank im Voraus.

+1

Ihre zweite Abfrage sollte funktionieren. Dis Sie versuchen, es lokal auszuführen? Auch eine eigenständige select-Anweisung ist in einer Prozedur nicht erlaubt. Geben Sie Beispieldaten an und replizieren Sie das Problem. – Utsav

+0

Ich habe der ursprünglichen Frage zusätzliche Informationen hinzugefügt ... – Morgs

+3

In Oracle gibt es keine leere Zeichenfolge. Wenn Sie möchten, dass Ihre Abfrage funktioniert, müssen Sie '! = ''' In 'is not null' umwandeln. Oder entfernen Sie diese Bedingung möglicherweise vollständig, wenn Sie alle Zeilen auswählen möchten, unabhängig davon, ob e.columnname null ist oder nicht. – Boneist

Antwort

3

nie vergessen, dass in Oracle SQL die '' wörtliche (leere Zeichenkette) ist die gleiche wie NULL, damit Ihr Prädikat e.ColumnName != '' entspricht e.ColumnName != null die immer NULL auswertet.

Das zweite Problem ist, dass Sie versuchen, einen booleschen Wert von Ihrem CASE auszugeben. Nein, Oracle kann keine booleschen Ausdrücke als Ergebnisse von Funktionen verwenden. (Lassen Sie sich CASE betrachtet eine Funktion zu sein, da ich nicht einen Eigennamen für diese Sprachkonstrukte jetzt erinnern kann.)

es auf diese Weise versuchen:

PROCEDURE GetBatchTotals(pEntityName VARCHAR DEFAULT NULL) IS 
BEGIN 
    -- Sample Query 
    SELECT ColumnName 
    FROM TableName e 
    WHERE 
    (pEntityName IS NULL AND e.ColumnName is not null) OR 
    (pEntityName IS NOT NULL AND e.ColumnName = pEntityName); 
END GetBatchTotals; 

Es gibt noch ein paar Probleme mit Ihrem Code, lassen sie haben sie behoben:

(1) Verwenden Sie nicht varchar, verwenden Sie stattdessen varchar2. Eine seltsame "Verbesserung" von Oracle, frag nicht.

(2) Für Gleichheit mit nicht NULL Werten Prädikate Sie das Prädikat weglassen können pEntityName is not null von einem des AND es, wird es impliziert werden.

(3) Prädikat e.ColumnName is not null filtert wirklich die Zeilen, wo e.ColumnNameNULL ist, die etwas anderes von Ihrer ursprünglichen Idee ist, alle Zeilen unabhängig von ihrem e.ColumnName Wert abzufragen.

(4) Entweder Schleife durch die Abfrage Ergebnisse oder Bulk holen sie in eine Sammlung oder geben Sie sie als Ref-Cursor. In PL/SQL müssen Sie setzen die Abfrageergebnisse in etwas! Lassen Sie sich eine Schleife durch die Abfrageergebnisse und spult die ColumnName Inhalte zu Server-Ausgabe ...

PROCEDURE GetBatchTotals(pEntityName VARCHAR2 DEFAULT NULL) IS 
BEGIN 
    for rec in (
    SELECT ColumnName 
    FROM TableName e 
    WHERE pEntityName IS NULL -- Just to select everything in the table 
     OR e.ColumnName = pEntityName 
) loop 
    dbms_output.put_line(rec.ColumnName); 
    end loop; 
END GetBatchTotals; 
+1

'e.ColumnName ist null' ... Ich denke du meinst" ist nicht null "hier? (Da die ursprünglichen Abfragen 'e.columnname! = ''') Hatten – Boneist

+0

Danke, ich bekomme das Konzept. Ja, Sie haben Recht, die Abfrage ist eigentlich für einen Cursor ... – Morgs

+1

@Boneist, danke. Offensichtlich hat es keinen Sinn, beim Schreiben von Code zu hetzen. :-) – nop77svk

-2

diese Struktur in der SQL-Arbeitsblatt mit Metadaten Versuchen:

declare 
    l_object_name varchar2(20) := null;-- your objects name 
begin 

    for l_rec in (
    select 
     e.object_name 
    from 
     all_objects e 
    where 
     (l_object_name is null and 
     1=1) or 
     (l_object_name is not null and 
     e.object_name = l_object_name)) 
    loop 
    dbms_output.put_line('Object found: '||l_rec.object_name); 
    end loop; 
end; 

testen.

+1

warum sich mit dem 'und 1 = 1' beschäftigen? Lass das einfach weg. – Boneist

+0

Ja, es ist optional. Aus ästhetischen Gründen - manche benutzen es, um darauf hinzuweisen, dass es "IN ALL" usw. ist. – Ychdziu

+1

Die Frage des OP lautete: "Wie kann ich das korrigieren?". Dies erklärt nicht, was in der Frage falsch ist, und präsentiert das OP nur mit einem anderen (anonymen) PL/SQL-Block, ohne eine Erklärung, warum oder wie es ihr Problem lösen würde. – MT0

1

ich nop77svk Antwort mochte er aber nie wirklich das Problem mit CASE geklärt (dh wie die Logik mit CASE richtig schreiben) . Also, um der Vollständigkeit halber, hier ist, wie Sie diese Logik mit CASE behandeln.

PROCEDURE GetBatchTotals(pEntityName VARCHAR2 DEFAULT NULL) IS 

    BEGIN 

    -- Sample Query 
    SELECT 
     e.ColumnName 
    FROM 
     Schema.TableName e 
    WHERE 
    1 = CASE 
      WHEN pEntityName IS NULL AND e.ColumnName IS NOT NULL 
       THEN 1 
      WHEN e.ColumName = pEntityName 
       THEN 1 
       ELSE 0 
     END 
    ); 

    END GetBatchTotals; 

In dieser besonderen Situation ist nop77svk Lösung wahrscheinlich der etwas einfacher/Reiniger Code :)

+0

Ich habe das Problem mit 'CASE' geklärt (... dass boolesche Werte im SQL-Kontext nicht gültig sind), aber Sie haben recht, ich habe mit' CASE' keine wirkliche Alternative vorgeschlagen. – nop77svk

+0

@ nop77svk: Entschuldigung, das ist, was ich meinte :), dass Sie nicht gezeigt haben, wie CASE "richtig" zu tun ..;) heh (aktualisierte Antwort ein bisschen, um diesen Schlamm aufzuräumen :)) – Ditto