SQL Server Join verhalten

mike024

New Member
Hallo!

Ich bin gerade beim portieren einer Anwendung auf MS SQL Server, die früher als Datenbankgrundlage MS Access verwendete.

Folgendes Problem bei einer Abfrage:

SELECT DISTINCT TAB_X.* FROM
TAB_X
LEFT JOIN TAB_Y ON TAB_X.ID = TAB_Y.TAB_XID
WHERE
RTrim(TAB_Y.STRING) + '' Like '%'

in worten: ich selektiere aus tabelle x werte abhängig von werten in der tabelle y, das funktioniert ja - aber wenn kein entsprechender datensatz der tabelle y zu tabelle x gefunden wurde dann sind die werte der tabelle y = NULL was auch noch kein problem darstellt.
Das unverständliche daran ist das selbst wenn ich z.B. 'X' mit dem String NULL wert verkette das ergebniss selbst wieder NULL ist?

Ich hab auch schon probiert wenn man über dieses ganze SQL Statement ein SELECT zieht ob dann die verkettung greift, aber leider nicht!

In Access funktioniert diese Abfrage.

Könnte mir bitte jemand den unterschied oder vorhegensweise der Abarbeitung der Abfrage im SQL Server erklären um diesem Probelem Herr zu werden.

Danke im voraus

mfg Mike
 
Last edited by a moderator:
in worten: ich selektiere aus tabelle x werte abhängig von werten in der tabelle y
Bitte beschreibe, was du willst. Nicht, was du versuchst.
Was soll dein Statement bewirken? Der gepostete Schnipsel lässt das nur schwer vermuten...
 
Das unverständliche daran ist das selbst wenn ich z.B. 'X' mit dem String NULL wert verkette das ergebniss selbst wieder NULL ist?

Daran muss man sich gewoehnen, ich habe es zwar bei den aktuellen Versionen nicht evaluiert aber bei 6.0 und 6.5 wurde noch alles, was mit NULL verbunden wird NULL.
Funktioniert so wie ein schwarzes Loch in einem alten Adventure Spiel ->
"Benutze Haus mit Schwarzem Loch" Ergebnis => "Schwarzes Loch". :)
Der Link zu concat() drueckt es so aus (auch wenn das eine MySQL Doku ist und nicht die vom MS-SQL Server ;) )
CONCAT() returns NULL if any argument is NULL.
Und der letzte Teil der Aussage gilt fuer so ziemlich alle Operationen da hilft nur ein etwas umstaendlicheres "IS NULL" (weiss grade nicht, ob getrennt oder zusammen geschrieben) evtl. in Kombination mit einem IF.
Was mir nicht transparent ist, was ein Vergelcih auf "LIKE %" bewirken soll. :confused:

Ciao,
Mercy.
 
Was mir nicht transparent ist, was ein Vergelcih auf "LIKE %" bewirken soll. :confused:
Vieleicht will er ja das prüfen:
Code:
WHERE TAB_Y.STRING IS NOT NULL
Leider hat er immer noch nicht geschrieben, wo er mit dem ganzen Ding hin will, sondern nur wie er glaubt, sein Ziel erreichen zu können.
 
Hallo zusammen,

also danke mal für die Antworten.

Wie schon beschrieben liegt das problem darin das NULL + String nicht NULL ergeben sollte.

Ich wollte nicht das ganze statement posten, aber villeicht seht ihr es dann was ich nicht finde:

SELECT distinct t_liegenschaft.ID,t_liegenschaft.LIEGID,
t_liegenschaft.Strasse + ' ' + t_liegenschaft.Hausnr + ' ' + t_liegenschaft.PLZ + ' ' + t_liegenschaft.Ort AS adresse,
t_liegenschaft.Wirtschaftskoerper, t_liegenschaft.DORIS_LINK,
--IIf(t_lieggrst.liegcntgg Is Null,0,t_lieggrst.liegcntgg) AS liegcnt,
liegcnt = CASE t_lieggrst.liegcntgg WHEN NULL THEN 0 ELSE t_lieggrst.liegcntgg END,
--IIf(t_liegver.liegvercnt Is Null,Null,'(' & t_liegver.liegvercnt & ')') AS liegvercntform,
liegvercntform = CASE t_liegver.liegvercnt WHEN NULL THEN NULL
ELSE '(' + CAST(t_liegver.liegvercnt as nvarchar) + ')' END,
liegfl.SumFLAECHE, t_liegenschaft.Datum_erinnerung

FROM (((t_liegenschaft LEFT JOIN
(SELECT count(T_LIEG_ZUW_GRST.liegid) as liegcntgg, T_LIEG_ZUW_GRST.liegid
FROM T_LIEG_ZUW_GRST
group by T_LIEG_ZUW_GRST.liegid
) AS t_lieggrst ON t_liegenschaft.LIEGID = t_lieggrst.liegid)

LEFT JOIN
(SELECT count(t_lieg_an_verkauf.liegid) as liegvercnt,t_lieg_an_verkauf.liegid
from t_lieg_an_verkauf
group by t_lieg_an_verkauf.liegid
) AS t_liegver ON t_liegenschaft.LIEGID = t_liegver.liegid)
LEFT JOIN
(SELECT T_LIEG_ZUW_GRST.LIEGID,
Sum(CASE IsNumeric(LDB_TBLBenuetzAbschn.FLAECHE)
WHEN 1 THEN LDB_TBLBenuetzAbschn.FLAECHE
ELSE 0 END) AS SumFLAECHE
FROM T_LIEG_ZUW_GRST INNER JOIN LDB_TBLBenuetzAbschn
ON (T_LIEG_ZUW_GRST.KGNR = LDB_TBLBenuetzAbschn.KGNR) AND (T_LIEG_ZUW_GRST.EZNR = LDB_TBLBenuetzAbschn.EZNR) AND (T_LIEG_ZUW_GRST.GSTNR = LDB_TBLBenuetzAbschn.GSTNR)
GROUP BY T_LIEG_ZUW_GRST.LIEGID

) AS liegfl ON t_liegenschaft.LIEGID = liegfl.LIEGID)
LEFT JOIN T_LIEG_ZUW_GRST ON t_liegenschaft.LIEGID = T_LIEG_ZUW_GRST.LIEGID

WHERE
t_liegenschaft.LIEGID Like '%' AND
t_liegenschaft.Wirtschaftskoerper Like '%' AND
t_liegenschaft.Strasse + ' ' + t_liegenschaft.PLZ + ' ' + t_liegenschaft.Ort Like '%' AND
t_liegenschaft.Objekttyp Like '%' AND t_liegenschaft.Eigentuemer Not Like 'AUFGELASSEN' AND
(RTrim(T_LIEG_ZUW_GRST.GSTNR + '') Like '%' OR RTrim(T_LIEG_ZUW_GRST.eznr + '') Like '%' OR
RTrim(T_LIEG_ZUW_GRST.kgnr + '') Like '%')

---------------------------

Die felder der Tabelle T_LIEG_ZUW_GRST im WHERE sind das problem da like '%' wenn das Feld NULL ist nicht true ist.

Ich habe das Problem zwar schon umgangen aber mich interessier die Ursache!

mfg Mike
 
Und du glaubst nun auch noch, dass sich das so einer anschaut? Ne, ganz bestimmt nicht. Pack das erstmal in
Code:
-Tags.
 
Also ist jetzt besser :confused:

Code:
SELECT distinct t_liegenschaft.ID,t_liegenschaft.LIEGID, 
t_liegenschaft.Strasse + ' ' + t_liegenschaft.Hausnr + ' ' + t_liegenschaft.PLZ + ' ' + t_liegenschaft.Ort AS adresse, 
t_liegenschaft.Wirtschaftskoerper, t_liegenschaft.DORIS_LINK, 
--IIf(t_lieggrst.liegcntgg Is Null,0,t_lieggrst.liegcntgg) AS liegcnt, 
liegcnt = CASE t_lieggrst.liegcntgg WHEN NULL THEN 0 ELSE t_lieggrst.liegcntgg END,
--IIf(t_liegver.liegvercnt Is Null,Null,'(' & t_liegver.liegvercnt & ')') AS liegvercntform, 
liegvercntform = CASE t_liegver.liegvercnt WHEN NULL THEN NULL 
ELSE '(' + CAST(t_liegver.liegvercnt as nvarchar) + ')' END,
liegfl.SumFLAECHE, t_liegenschaft.Datum_erinnerung

FROM (((t_liegenschaft LEFT JOIN 
(SELECT count(T_LIEG_ZUW_GRST.liegid) as liegcntgg, T_LIEG_ZUW_GRST.liegid 
FROM T_LIEG_ZUW_GRST 
group by T_LIEG_ZUW_GRST.liegid
) AS t_lieggrst ON t_liegenschaft.LIEGID = t_lieggrst.liegid) 

LEFT JOIN 
(SELECT count(t_lieg_an_verkauf.liegid) as liegvercnt,t_lieg_an_verkauf.liegid
from t_lieg_an_verkauf
group by t_lieg_an_verkauf.liegid
) AS t_liegver ON t_liegenschaft.LIEGID = t_liegver.liegid) 
LEFT JOIN 
(SELECT T_LIEG_ZUW_GRST.LIEGID, 
Sum(CASE IsNumeric(LDB_TBLBenuetzAbschn.FLAECHE)
WHEN 1 THEN LDB_TBLBenuetzAbschn.FLAECHE
ELSE 0 END) AS SumFLAECHE
FROM T_LIEG_ZUW_GRST INNER JOIN LDB_TBLBenuetzAbschn 
ON (T_LIEG_ZUW_GRST.KGNR = LDB_TBLBenuetzAbschn.KGNR) AND (T_LIEG_ZUW_GRST.EZNR = LDB_TBLBenuetzAbschn.EZNR) AND (T_LIEG_ZUW_GRST.GSTNR = LDB_TBLBenuetzAbschn.GSTNR)
GROUP BY T_LIEG_ZUW_GRST.LIEGID

) AS liegfl ON t_liegenschaft.LIEGID = liegfl.LIEGID) 
LEFT JOIN T_LIEG_ZUW_GRST ON t_liegenschaft.LIEGID = T_LIEG_ZUW_GRST.LIEGID

WHERE 
t_liegenschaft.LIEGID Like '%' AND 
t_liegenschaft.Wirtschaftskoerper Like '%' AND 
t_liegenschaft.Strasse + ' ' + t_liegenschaft.PLZ + ' ' + t_liegenschaft.Ort Like '%' AND 
t_liegenschaft.Objekttyp Like '%' AND t_liegenschaft.Eigentuemer Not Like 'AUFGELASSEN' AND 
(RTrim(T_LIEG_ZUW_GRST.GSTNR + '') Like '%' OR RTrim(T_LIEG_ZUW_GRST.eznr + '') Like '%' OR 
RTrim(T_LIEG_ZUW_GRST.kgnr + '') Like '%')
 
Also,

ich beschreibe das ganze nochmal genau so wie es im Programm abläuft -->

Die werte für die Strings bei den Like Statements unterhalb sind Werte die aus Combos oder Textboxen kommen und zur Filterung des dienen. Die Like '%' sind jene Werte die nicht angegeben oder ausgefüllt wurden.

Wie schon erwähnt :
Daran muss man sich gewoehnen, ich habe es zwar bei den aktuellen Versionen nicht evaluiert aber bei 6.0 und 6.5 wurde noch alles, was mit NULL verbunden wird NULL
was ja auch kein problem ist. Wenn man es weis sollte man es mit CASE umgehen können.

Hier ein Bsp. von einem Case mit dem Feld aus dem Join

Code:
SELECT
 
CASE T_LIEG_ZUW_GRST.KGNR WHEN NULL THEN 'xxxxx' ELSE T_LIEG_ZUW_GRST.KGNR END AS KG, 
 
T_LIEGENSCHAFT.LIEGID
 
FROM
T_LIEGENSCHAFT LEFT JOIN
T_LIEG_ZUW_GRST ON T_LIEGENSCHAFT.LIEGID = T_LIEG_ZUW_GRST.LIEGID
 
order by kg asc

dazu gibts Bild1 und das ergebniss verstehe ich nicht.

tut mir leid wenn ich nicht alle funktionen des Forums nutze aber ich bin ein neuling auf diesem gebiet!

mfg Mike
 

Attachments

  • Bild1.JPG
    Bild1.JPG
    36.7 KB · Views: 102
Die Like '%' sind jene Werte die nicht angegeben oder ausgefüllt wurden.
Mir scheint, die wahre Lösung des Problems ist, die nicht angegebenen Spalten auch nicht zu vergleichen.
(Ich nehme an, dass table.column LIKE '%' bedeuten soll: "es ist egal".)

Generell sollte man beachten, dass NULL nicht vergleichbar ist, außer mit IS NULL oder IS NOT NULL. NULL lässt sich nicht mit LIKE, = oder != vergleichen, da es ein undefinierter Wert ist. (Wenn eine SQL-Implemetierung es doch tut, dann ist das ein Verhalten, auf das man sich besser nicht verlassen sollte.)

Deshalb ist auch z.B. ein solcher Vergleich syntaktisch falsch:
Code:
WHERE table.column = NULL

Um einen Wert einer Spalte auf leer oder NULL zu testen braucht es das hier:
Code:
WHERE table.column = '' OR table.column IS NULL
 
Wenn eine SQL-Implemetierung es doch tut, dann ist das ein Verhalten, auf das man sich besser nicht verlassen sollte.
Genau das geschieht auch; Jeder Operator / Jede Funktion behandelt NULL nach (je Implementierung) definierten Regeln, insofern ist das schon verlaesslich allerdings nicht Versionsuebergreifend.
Bis MS-SQL 6.5 lieferte ein Vergleich mit NULL immer WAHR, danach immer FALSCH. Hier auch nochmal der Verweis auf den Link von JPieper, es ist i.d.R. sogar dokumentiert aber halt nicht unbedingt einheitlich und von Bestand zwischen unterschiedlichen Versionen.
Die einzige verlaessliche Funktion ist tatsaechlich die ueber IS NULL und dessen Negation.

Uebrigens waere es wesentlich performanter (vorausgesetzt der SQL-code wird dynamisch aus einem Programm generiert), die irrelevanten Where-Abschnitte ganz wegzulassen als dieses "LIKE %" also "ungefaehr so aehnlich wie alles Moegliche" zu verbauen.

Achso ja und ... falls denn auch tatsaechlich mal NULL-Values in als Text zu verarbeitenden Spalten gespeichert werden sollten ist noch VarChar eine nicht unnuetze Variante (Leerstring speichern).
Ansonsten wuerde ich persoenlich NULL nur bei tatsaechlich unterschiedlichen Satzarten oder nicht vorhandenen BLOB's einsetzen.

Ciao,
Mercy.
 
Danke für die raschen Antworten,

da ich noch SQL Server neuling bin muss ich mich erst an das doch sehr unterschiedliche verhalten zu Access gewöhnen (nicht nur im bezug auf NULL).

Auf jeden Fall haben mir die Antworten geholfen und die Abfrage ist wieder funktionstüchtig.

Da ich ja schon beim basteln war hab ich natürlich auch die Filterparameter diesmal dyn. zusammengesetzt wie vorgeschlagen wurde.

mfg Mike
 
Wobei mir noch eingefallen ist,
wenn Du eh gerade die engine umstellst und die NULL Eintraege eigentlich Leerstrings sein sollen, dann bietet sich ein Constraint "Not Null" auf den Spalten samt einem "default value '' " an siehe Manual dort DDL dort Create Table.

Ciao,
Mercy.
 
Back
Top