PL / SQL: Dynamische Where-Bedingung

Hallo,

ich habe eine Abfrage, die mir Artikeldaten in Abhängigkeit
davon zurückgibt, ob die Variable v_artikelnummer einen Wert enthält oder nicht.
Wenn die Variable leer ist, sollen alle Artikel angezeigt werden,
ansonsten soll gefiltert werden.

Ich habe vereinfacht dargestellt folgenden Lösungsansatz ausprobiert:

select * from artikel
where ((v_artikelnummer is not null and artikelnummer = v_artikelnummer)
or v_artikelnummer is null);

Das Problem ist nur, die Abfrage ist deutlich langsamer wie diese: (5Sek. zu 0.02Sek.)

select * from artikel
where artikelnummer = v_artikelnummer;

Das heißt, ich muss das SQL ggf. doch als Zeichenkette zusammenbauen, und mit execute immediate ausführen.
Das will ich eigentlich verhindern, da das gesamte SQL sehr umfangreich ist.

Was mich interessiert, wieso ist das SQL soviel langsamer? Fallen euch andere Lösungsansätze ein?

Ich arbeite mit Orace 9.

Danke im voraus.

Hallo,

Tom Kyte hat gerade einen interessanten Artikel über genau dieses Problem (dynamische WHERE Clauses) auf OTN. Dies sollte für dein Problem die Lösung bereithalten

http://www.oracle.com/technology/oramag/oracle/09-ju…

Gruss

Hallo FreddyIT,

durch die NULL-Abfrage erzwingst Du einen Full-Tablescan der Tabelle, da NULL-Werte nicht in einem Index aufgenommen werden. Geschickter wäre es, wenn Du vorher im PL/SQL-Code feststellst, ob die Variable NULL ist und dann die entsprechende Abfrage zu starten. Dann hättest Du wenigsten nur für nicht gefüllte Variablen ein langsame Abfrage.

Solltest Du jetzt antworten, aber ich habe mehrere solche Variablen und dass ergibt ja 2^n Varianten, dann hast Du
a) Recht und
b) den Grund gefunden eventuell Dein Datenmodell und Deine Behandlung von NULL-Werten beim Import zu überdenken.

MfG Georg V.

Hallo,

danke für die Antworten.
Ich habe mich jetzt doch für die Lösung mit dem zusammengesetzen SQL
entschieden, welches dann mit EXECUTE IMMEDIATE ausgeführt wird.
Das SQL ist auch einigermaßen übersichtlich geblieben. :wink:

MfG

Hallo,

arbeite mit MS-SQL und zeige auch in Abhängigkeit von der Benutzerauswahl alle oder ausgewählte Datensätze an.

Meine Lösung:

Select * from Artikel
where artikelnummer = Case when IsNull(@artikelnummer,0)=0 then artikelnummer else @artikelnummer END

  • @artikelnummer ist die Variable die den eventuellen Filter enthält
  • in meinem Beispiel sind artikelnummer und @artikelnummer Zahlen
  • mein Beispiel vergleicht @artikelnummer, enthält sie einen Wert dann soll artikelnummer = @artikelnummer sein, ansonsten vergleicht er die artikelnummer des Datensatzes mit sich selbst (artikelnummer = artikelnummer)
  • IsNull prüft auf Leerwert, wenn dies der Fall ist, soll er die Ziffer 0 einsetzen

Gruß EPa