View Full Version : SQL set oder select into mit dynamischer Selektion
Auch bei Dynamic muss der Programmierer ja wissen, welche Felder er nicht in die Where-Klausel aufnimmt.
Also kann er bei der statischen Variante einfach die NULL-Anzeiger für die nicht benötigten Felder setzen verwenden, da dies so wirkt, als wäre die Bedingung nicht vorhanden.
Denn mit NULL kann man nur mit " is null" vergleichen und sonst nicht.
@dibe
Wenn du eine Spalte mit NULL vergleichst, ist das Ergebnis NULL.
Da du aber alle mit Or verknüpfst, benötigst du mindestens 1 Bedingung die nicht NULL sondern Wahr ist um zum Ergebnis zu kommen.
In RPG Kann man aber NULL halt nur mit einem NULL-Indikator markieren.
Wenn du also z.B. Null2 bis Null6 mit -1 belegst, muss "Feld1 = : Wert1" zum Ziel führen, oder auch nicht wenn es ebenso ein akzeptables Ergebnis ist.
Ach ja:
Die 2. Variante von Birgitta ist dieselbe wie die in der ersten Antwort, nur komplizierter geschrieben.
Warum soll ich Col1 mit sich selber vergleichen wenn die Variable leer ist und ich doch eigentlich alles mit or verknüpfe?
dschroeder
01-10-25, 14:19
Die Antwort von Baldur klingt interessant. Aber verstanden habe ich sie auch nicht.
Im where habe ich noch nie Null Indikators gesetzt. Was bedeutet denn:
where ( feld1 = :wert1 :Null1)
or feld2 = :wert2 :Null2)
or feld3 = :wert3 :Null3)
Ich denke, du meinst, dass ich mehrere numerische Variablen Null1, Null2, ... im RPG deklariere und z.B. Null1 und Null3 auf -1 setze? Dann würde nur die Selektion für feld2 geprüft? Ist das so?
Falls ja, ist das eine coole Idee, aber ich verstehe noch nicht, weshalb das funktioniert.
select count(*)
from ...
where ...
and col1 between :low1 and :high2
and col2 between :low2 and :high2
...
wenn in :lowx, :highx lowval bzw highval ist die Bedingung immer true
schreibe ich einen Wert in beide rein, nimmt er nur diesen
et voila!
mit dem null habe ich Bedenken, das sieht mir nach einer Fehlerbedingung aus (Vergleiche mit einem Nuulwert gehen nur mit is null, bzw. is not null
D*B
dschroeder
01-10-25, 14:52
Die Lösung von Dieter Bender finde ich auch cool. Gefällt mir persönlich sogar am besten, weil sie
statisches SQL ermöglicht und ohne Nullwerte auskommt (ist ja in RPG oft ungewohnt).
(Die Lösung von Baldur habe ich immer noch nicht verstanden)
Das mit dem NULL ist ja Absicht, da das Ergebnis nicht relavant, also ebenso nicht TRUE ist.
Da es ja eine Bedingung für den Ausschluss des dynamischen SQL's gibt, kann dieselbe Bedingung auch für das statische SQL gelten.
NULL und Null-Anzeiger:
Eine Where-Klausel will als Ergebnis ein WAHR haben, dabei wird boolsche Algebra ausgewertet.
Generell gilt: wenn ein Teil-Ausdruck NULL ist, wird der gesamte Ausdruck NULL.
folglich:
where Feld = : Parm : NullInd
ergibt: Wenn Parm nicht NULL ist (NullInd <> -1) und Feld = Parm ist, ist die Bedingung wahr.
Wenn du also NullInd auf -1 setzt ist das Ergebnis nicht Wahr, wenn du es auf 0 setzt ist das Ergebnis wahr.
Null-Idikatoren können nicht nur bei Results angewendet werden sondern auch bei Parametern um z.B. NULL beim Insert/Update zu schreiben.
NullInd ist aber nur nötig, wenn es keine andere Ausschlussbedingung gibt:
Also
where (: P1 = 0 or : P1 = Feld1 )
and (: P2 = '' or : P2 = Feld2 )
usw. usf.
where Feld = : Parm : NullInd
wenn ich den nullind setze, steht da
where Feld = null
und das ist illegal. Selbst wenn es das durchlässt hätte ich Bedenken. Wenn das bei einem PTF oder release korrigiert wird, fällt das pgm auf die Schnauze.
Was mich verwirrt ist das OR
Der Anwender selektiert
Name: Hugo
Land: D
Verkäufer: 37
Artikel: --> egal
Farbe: --> egal
Größe: --> egal
Also ... where Name = 'Hugo' and Land = 'D' and Verkäufer = 37
oder in der Fuerchau Schreibweise
ind1 = 0
ind2 = 0
ind3 = 0
ind4 = -1
ind5 = -1
ind6 = -1
Na = 'Hugo'
LN = 'D'
VK = 37
AR =' '
FA = ' '
GR = 0
where (Name = :Na :ind1
or Land = :LN :ind2
or Verkäufer = :VK :ind3
or Artikel = :AR :ind4
or Farbe = :FA :ind5
or Größe = :GR :in6)
Das verstehe ich nicht.
Dietlind Beck
Frage: Sind die Suchkriterien bei And oder bei Oder?
I.d.R. gelten Suchbedingungen mit And, also meine letzte Variante, da die Suchkriterien ja leer sind:
where ( :Na = '' or Name = :Na)
and (:LN = '' or Land = :LN )
usw.
Somit gilt: Wenn NA = Leer ist, spielt Name keine Rolle, wenn LN = leer ist, spielt Land keine Rolle, wenn beide nicht leer sind, muss beides stimmen.
Ds klappt auch mit 0-Werten (es sei denn das 0 zulässig ist, dann brauchst du den NullInd) oder Datum mit '0001-01-01' (*loval).
Die Kombination ergibt sich eben aus den Inhalten und das lässt sich beliebig fortsetzen.
Sogar Indizes können dann verwendet werden.
NULL wird dann gar nicht benötigt. Deine Fragestellung hat halt ein wenig verwirrt.
Wobei ich mich Frage, was du da mit einem Count(*) willst, da du i.d.R. ja ein Resultset willst.
Den Count über das Ergebnis kann man mit "count(*) over () AnzahlZeilen" bekommen.
Wo liegt denn jetzt überhaupt das Problem?
Darin, dass die Spalten NULL fähig sind und falls keine Auswahl erfolgt ist alle Zeilen (unabhängig davon ob das Feld in der Zeile einen NULL-Wert enthält oder nicht) angezeigt werden sollen?
NULL-Werte müssen separat geprüft werden, da sie außerhalb des gültigen Bereichs liegen. Da NULL-Werte nicht direkt mit anderen NULL-Werten verglichen werden können, ist das Ganze ein bisschen tricky.
... aber die folgende Syntax sollte auch bei NULL-fähigen Spalten (im statischen SQL funktionieren), d.h. wenn in dem entsprechenden Feld (:HostCol) kein Wert erfasst wurde, werden alle Zeilen incl. den Zeilen, die in der entsprechenden Spalte NULL-Werte enthalten ausgegeben.
Where Col1 is not distinct from Case When :HostCol1 > '' Then :HostCol1 else Col1 End
and Col1 is not distinct from Case When :HostCol2 >= -99999999 Then :HostCol2 Else Col2 End
and MyDate is not distinct from Case When :HostCol3 > '0001-01-01' Then :HostCol3 Else Col3 End
and ...
Es ging nicht um die Frage wie NULL abgefragt wrd, dafür gibts ebenso "is null".
Es ging nur darum, bei bestimmten Abfragemethoden einen Parameter als NULL-Wert zu übergeben um die Abfrage ggf. ungültig zu machen.
NULL kann man im Zweifel auch mit einem Default vergleichen, was ich ebenso gerne mache:
coalesce(Feld, Default) = :Parameter
Aber, darum ging es in diesem Thread überhaupt nicht.
Deine komplizierte Abfrage ist da schon eher mit Dieters Beispiel "between" ablösbar.
Im IBM i Umfeld habe ich es konkret noch nicht erlebt, dass man NULL-Werte vernünftig verwendet.
In einer View wird dann lieber per coalesce ein NULL-Wert wieder ausgeschlossen, da man wohl in RPG nur bedingt damit umgehen kann.
Die Eingangsfrage kann mit dem simplen statischen Where in meinem Beispiel gelöst werden.
Simplify vs. complicated;-).