Anmelden

View Full Version : SQL Nullwerte nicht zulässig trotz coalesce oder ifnull



Seiten : [1] 2

Progras
17-11-16, 12:24
Hallo,

ich komme nicht weiter. Dieses SQL Statement liefert mir die Fehlermeldung 'Nullwerte für Spalte oder Variable TEAT05 nicht zulässig. Wenn ich eine bestimmte soid4 auswähle, die einen Wert enthält, dann funktioniert es. Was mache ich falsch?

update tst01pf t
set t.teat05 = (select ifnull(s.soeipr, 0)
from son01pf s
where t.tetenr = s.soid4
and s.sofa =01
and s.sodtbi >= 161231
and s.soeipr <> 0
and s.soeipr is not null
and s.soid1=30600
and s.sosts = 0)
where t.tefa = 10 and tetenr=11

Gruß

Progras

BenderD
17-11-16, 12:51
... klemmt, wenn keine Zeile zurück kommt!

statt select ifnull(...) from ...
set (coalesce((select ... from...), 0)

außerdem geht das auch schief, wenn mehr als eine Zeile zurück kommt

D*B

andreaspr@aon.at
17-11-16, 12:52
IFNULL ersetzt dir nur den Wert für eine Spalte einer VORHANDENEN Zeile.
Wenn der Datensatz nicht existiert, kann auch kein Ersatzwert gesetzt werden.

Fuerchau
17-11-16, 13:45
NULLIF(Feld, 0) entspricht: case when feld =0 then null else feld end
COALESCE(Feld, 0) entspricht: case when feld is null then 0 else feld end

Da dein Zielfeld aber NULL nicht erlaubt (siehe Fehlermeldung) darfst du nicht NULL im Ergabnis haben.
Also wäre Dieters Lösung "select coalesce(feld, 0) from ... where ..." die Richtige.
Allerdings wird trotzdem NULL geliefert, wenn die Where-Klausel nicht fündig wird.
Also "coalesce((select feld from ... where ...), 0)" ist dann fast perfekt.
Um auszuschließen, dass mehr als 1 Zeile kommt, falls die Daten es zulassen, kann man noch ergänzen:
coalesce((select feld from ... where ... fetch first 1 rows only), 0)

Progras
17-11-16, 14:10
Super, danke Fuerchau und BenderD, das hat mir beides gut weitergeholfen. Die Abfrage funktioniert nun.

Aber wie Fuerchau schon beschrieben hat, wird 0 geliefert, wenn nichts gefunden wird (Auch mit 'fetch first 1 rows only'). Wie kann ich es vermeiden, dass das Feld teat05 überschrieben wird, wenn das Select Ergebnis 0 liefert?

Zum Verständnis meiner Abfrage: Ich möchte, abhängig von der Artikelnummer, die Preise in son01pf der Firma 01 in die tst1pf der Firma 10 schreiben. Das sind ca. 700 Preise. Aber das SQL updated das Feld teat05 in allen 8000 Zeilen der Firma 10 in der tst01pf.

update tst01pf t
set t.teat05= coalesce((select s.soeipr
from son01pf s
where t.tetenr = s.soid4
and s.sofa =01
and s.sodtbi >= 161231
and s.soeipr <> 0
and s.soeipr is not null
and s.soid1=30600
and t.tefa = 10
and s.sosts = 0
fetch first 1 rows only), 0)
where t.tefa = 10

Gruß

Progras

Fuerchau
17-11-16, 14:15
coalesce((select nullif(soeipr, 0)...), teat05)

Wenn "soeipr = 0" dann nimm NULL, wenn das Ergebnis des Selects NULL, dann nimm den Ursprung.

B.Hauser
17-11-16, 14:24
Die korrekte Syntax für den Update einer Tabelle auf Basis einer zweiten Tabelle sieht wie folgt aus:


Update YourTable a
set YourColumn = (Select Distinct YourNextColumn
From NextTable b
Where a.Key1 = b.Key1
and a.Key2 = b.Key2
...
and a.KeyN = b.KeyN)
Where Exists (Select *
from NextTable c
Where a.Key1 = c.Key1
and a.Key2 = c.Key2
...
and a.KeyN = c.KeyN);

Dadurch wird sichergestellt, dass für jeden Datensatz aus der ersten Datei genau ein Datensatz aus der zweiten Datei gefunden wird. Fehlen Datensätze in der ersten Datei oder der zweiten Datei, werden diese elimiert bzw. erfolgt kein Update auf den entsprechenden Satz.

Damit ist eine explizite Konvertierung von NULL-Werten mittels COALESCE oder IFNULL nicht erforderlich.

Doppelte Datensätze werden ebenfalls vermieden.

Birgitta

Fuerchau
17-11-16, 14:32
Der "Distinct" (= Eindeutig) sorgt nur dafür, dass es keine doppelten Werte gibt.
Er verhindert nicht, dass mehr als 1 Zeile zurückkommt wenn es mehrere unterschiedliche Werte gibt.

KingofKning
18-11-16, 07:29
update tst01pf t
set t.teat05= coalesce((select s.soeipr
from son01pf s
where t.tetenr = s.soid4
and s.sofa =01
and s.sodtbi >= 161231
and s.soeipr <> 0
and s.soeipr is not null
and s.soid1=30600
and t.tefa = 10
and s.sosts = 0
fetch first 1 rows only), 0)
where t.tefa = 10
Progras

Da sieht mir schwer nach einem ERP System aus Koblenz aus ;-)

GG 4943

BenderD
18-11-16, 08:09
Super, danke Fuerchau und BenderD, das hat mir beides gut weitergeholfen. Die Abfrage funktioniert nun.

Aber wie Fuerchau schon beschrieben hat, wird 0 geliefert, wenn nichts gefunden wird (Auch mit 'fetch first 1 rows only'). Wie kann ich es vermeiden, dass das Feld teat05 überschrieben wird, wenn das Select Ergebnis 0 liefert?

Zum Verständnis meiner Abfrage: Ich möchte, abhängig von der Artikelnummer, die Preise in son01pf der Firma 01 in die tst1pf der Firma 10 schreiben. Das sind ca. 700 Preise. Aber das SQL updated das Feld teat05 in allen 8000 Zeilen der Firma 10 in der tst01pf.

update tst01pf t
set t.teat05= coalesce((select s.soeipr
from son01pf s
where t.tetenr = s.soid4
and s.sofa =01
and s.sodtbi >= 161231
and s.soeipr <> 0
and s.soeipr is not null
and s.soid1=30600
and t.tefa = 10
and s.sosts = 0
fetch first 1 rows only), 0)
where t.tefa = 10

Gruß

Progras

... das lässt sich auch einfach so heilen:
update tst01pf t
set t.teat05= coalesce((select s.soeipr
from son01pf s
where t.tetenr = s.soid4
and s.sofa =01
and s.sodtbi >= 161231
and s.soeipr <> 0
and s.soeipr is not null
and s.soid1=30600
and t.tefa = 10
and s.sosts = 0
fetch first 1 rows only), t.teat05)
where t.tefa = 10

wobei der fetch first möglicherweise nicht das ist, was man haben will, der holt nämlich der erstbesten, den er gerade findet. Da sollte man schon mal prüfen, ob es da eine ausreichende Schlüsselbeziehung gibt, oder eher mit min oder select max(s.soeipr) oder min(...) arbeiten.

D*B