lombaseggel
Goto Top

SQL liefert falsche Werte bei IS NULL

Hallo alle zusammen,

wir haben hier ein mittelgroßes Problem und eins vorweg, ich bin alles andere als ein SQL Profi face-smile
Wir benutzen Access schon seit ein paar Jahren um auf unserem MS SQL 2000 Server Abfragen zu erstellen.
In letzter Zeit haben wir ab und zu mal bei einer monatlichen Abfrage das Phenomen das falsche Werte geliefert werden.

Die Sicht beinhaltet das Kriterium FELD1 = IS NULL
d.h. nur die Datensätze bei denen kein Wert eingetragen ist sollen in einem späteren Schritt angezeigt werden.
Ab und zu rutscht aber immer wieder ein Feld rein das aber einen Wert enthällt!
Ich finde dann auf dem Ausdruck der Datensätze, vereinzelt welche bei denen das Feld einen Inhalt hat, und das teilweise schon seit Jahren.

Wir kann das sein? Hat jemand von euch eine Idee wo hier evnt das Problem verborgen sein könnte? Kann der SQL sich z.B "verschlucken"? Die Abfragen sind sehr groß und erstrecken sich über ca 45.000 Datensätze. Leider ist unser Entwickler der das "System" entwickelt hat nicht mehr im Unternehmen.

Über Ideen würde ich mich freuen den ich bin am Ende mit meinem Latein.

Vielen Dank für eure Hilfe

Content-Key: 118556

Url: https://administrator.de/contentid/118556

Printed on: April 16, 2024 at 21:04 o'clock

Member: Biber
Biber Jun 19, 2009 at 08:44:49 (UTC)
Goto Top
Moin lombaseggel,

willkommen im Forum.

Auch wenn ich fest davon ausgehen, dass "FELD1 = IS NULL" ein Tippfehler ist und in Wirklichkeit "FELD1 IS NULL" dort steht - bitte poste doch die Abfrage.

Das Access eventuell Datensätze verschluckt, nur weil das irgendwelche Redmonder zusammengeschrotet haben - nein, das können wir ausschließen.


Grüße
Biber
Member: lombaseggel
lombaseggel Jun 19, 2009 at 08:49:16 (UTC)
Goto Top
Danke schon mal für die Antwort,
ja es war ein Tippfehler face-smile Es geht um die SageBelegnummer

hier der Syntax:

SELECT dbo.MT_Zertifikate.Zert_Nr, dbo.MT_Zertifikate.Ausgang, dbo.MT_Zertifikate.Zertifizierdatum, dbo.MT_Zertifikate.Zertifikatstyp,
dbo.MT_Zertifikate.SageBelegnummer, dbo.getsamount(dbo.MT_Zertifikate.Zertifikatstyp) AS [Amount S], dbo.MT_Zertifikate.LaborID,
dbo.MT_Zertifikate.LocalProjectNo, dbo.MT_Zertifikate.S_Number, dbo.MT_Zertifikatstyp.Beschreibung, dbo.MT_Zertifikate.ZID,
dbo.MT_Zertifikate.ProductID, dbo.MT_Zertifikate.gültig_bis, dbo.MT_Zertifikate.Zurückziehdatum, dbo.MT_Zertifikate.Produktbez_engl,
dbo.MT_Zertifikate.Typ_eng, dbo.MT_Adressen.AdressID, dbo.MT_Adressen.Abkürzung, dbo.MT_Zertifikate.ModSpecial
FROM dbo.MT_Zertifikate INNER JOIN
dbo.MT_Zertifikatstyp ON dbo.MT_Zertifikate.Zertifikatstyp = dbo.MT_Zertifikatstyp.Zertifikatstyp INNER JOIN
dbo.MT_Auftrag ON dbo.MT_Zertifikate.AID = dbo.MT_Auftrag.AID INNER JOIN
dbo.MT_Adressen ON dbo.MT_Auftrag.KID = dbo.MT_Adressen.AdressID
WHERE (dbo.MT_Zertifikate.Ausgang IS NOT NULL) AND (dbo.MT_Zertifikate.Zertifizierdatum >= CONVERT(DATETIME, '2006-01-01 00:00:00', 102)) AND
(dbo.MT_Zertifikate.SageBelegnummer IS NULL) AND (dbo.MT_Zertifikate.Zertifikatstyp = 1 OR
dbo.MT_Zertifikate.Zertifikatstyp = 6 OR
dbo.MT_Zertifikate.Zertifikatstyp = 2 OR
dbo.MT_Zertifikate.Zertifikatstyp = 8 OR
dbo.MT_Zertifikate.Zertifikatstyp = 9 OR
dbo.MT_Zertifikate.Zertifikatstyp = 12 OR
dbo.MT_Zertifikate.Zertifikatstyp = 10 OR
dbo.MT_Zertifikate.Zertifikatstyp = 11 OR
dbo.MT_Zertifikate.Zertifikatstyp = 13 OR
dbo.MT_Zertifikate.Zertifikatstyp = 14 OR
dbo.MT_Zertifikate.Zertifikatstyp = 7 OR
dbo.MT_Zertifikate.Zertifikatstyp = 5 OR
dbo.MT_Zertifikate.Zertifikatstyp = 16 OR
dbo.MT_Zertifikate.Zertifikatstyp = 15 OR
dbo.MT_Zertifikate.Zertifikatstyp = 18 OR
dbo.MT_Zertifikate.Zertifikatstyp = 3 OR
dbo.MT_Zertifikate.Zertifikatstyp = 19)
Member: dog
dog Jun 19, 2009 at 09:13:50 (UTC)
Goto Top
Ich hab mir das SQL zwar noch nicht angeschaut aber zwei Dinge vorweg:

1. NULL und "Feld ist leer" sind zwei verschiedene Dinge. NULL ist ein konkreter Feldwert, eine Prüfung auf "Leer" sähe anders aus.

2. Dein SQL etwas geordnet

SELECT 
	dbo.MT_Zertifikate.Zert_Nr, 
	dbo.MT_Zertifikate.Ausgang, 
	dbo.MT_Zertifikate.Zertifizierdatum, 
	dbo.MT_Zertifikate.Zertifikatstyp,
	dbo.MT_Zertifikate.SageBelegnummer,
	dbo.getsamount(dbo.MT_Zertifikate.Zertifikatstyp) AS [Amount S], 
	dbo.MT_Zertifikate.LaborID,
	dbo.MT_Zertifikate.LocalProjectNo, 
	dbo.MT_Zertifikate.S_Number, 
	dbo.MT_Zertifikatstyp.Beschreibung, 
	dbo.MT_Zertifikate.ZID,
	dbo.MT_Zertifikate.ProductID, 
	dbo.MT_Zertifikate.gültig_bis, 
	dbo.MT_Zertifikate.Zurückziehdatum, 
	dbo.MT_Zertifikate.Produktbez_engl,
	dbo.MT_Zertifikate.Typ_eng, 
	dbo.MT_Adressen.AdressID, 
	dbo.MT_Adressen.Abkürzung, 
	dbo.MT_Zertifikate.ModSpecial
FROM 
	dbo.MT_Zertifikate 
INNER JOIN
	dbo.MT_Zertifikatstyp ON dbo.MT_Zertifikate.Zertifikatstyp = dbo.MT_Zertifikatstyp.Zertifikatstyp 
INNER JOIN
	dbo.MT_Auftrag ON dbo.MT_Zertifikate.AID = dbo.MT_Auftrag.AID 
INNER JOIN
	dbo.MT_Adressen ON dbo.MT_Auftrag.KID = dbo.MT_Adressen.AdressID
WHERE 
	(dbo.MT_Zertifikate.Ausgang IS NOT NULL) 
	AND 
		(dbo.MT_Zertifikate.Zertifizierdatum >= CONVERT(DATETIME, '2006-01-01 00:00:00', 102))   
		AND
			(dbo.MT_Zertifikate.SageBelegnummer IS NULL) 
			AND 
				(
					dbo.MT_Zertifikate.Zertifikatstyp = 1 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 6 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 2 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 8 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 9 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 12 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 10 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 11 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 13 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 14 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 7 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 5 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 16 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 15 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 18 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 3 OR
					dbo.MT_Zertifikate.Zertifikatstyp = 19
				)

Grüße

Max
Member: lombaseggel
lombaseggel Jun 19, 2009 at 09:18:09 (UTC)
Goto Top
Ups, das mit der Formatierungshilfe ist mir absolut entgangen! Danke

Ok ich als SQL Laie dachte IS NULL bedeutet das Feld ist leer,
wenn IS NULL einen bestimmten Wert vorgibt könnte die Ursache darin liegen!?
Member: dog
dog Jun 19, 2009 at 10:36:12 (UTC)
Goto Top
Also prinzipiell sollte es nicht vorkommen, dass eine Spalte die mit "IS NULL" gebunden ist im Ergebnis konkrete Werte vorkommen.
Wenn du nur einmal folgenden Query ausführst, gibt es dann immer noch Spalten mit Werten?
SELECT * FRPM dbo.MT_Zertifikate WHERE SageBelegnummer IS NULL 

Welchen Spaltentyp hat SageBelegnummer?

Grüße

Max
Member: lombaseggel
lombaseggel Jun 19, 2009 at 10:54:38 (UTC)
Goto Top
Wenn ich die aktuelle Abfrage ausführe erscheinen auch keine Datensätze bei denen im Sage Feld etwas steht.
Das passiert nur sporadisch. Auch deine Abfrage liefert keine "falschen" Werte.

Der Datentyp ist nvarchar

Danke Gruss Marc
Member: filippg
filippg Jun 20, 2009 at 01:30:30 (UTC)
Goto Top
Jaa... dann ändere doch eine Anfrage mal in (NOT ((dbo.MT_Zertifikate.Ausgang IS NULL) OR (dbo.MT_Zertifikate.Ausgang = '')))

Gruß

Filipp

PS: dieses NULL-Ding ist echt Teufelszeug, ich bin dem auch schon oft genug aufgesessen.
Member: lombaseggel
lombaseggel Jun 22, 2009 at 08:13:57 (UTC)
Goto Top
Das Problem bezog sich auf das Sagefeld das leer sein muss für diese Art von Vorgang.
Analog dazu:
(NOT ((dbo.MT_Zertifikate.Sage IS NULL) OR (dbo.MT_Zertifikate.Sage = '')))
?
Kannst du mir evnt etwas mehr erklären warum das NULL, Probleme macht/machen kann in deinen Augen?
Bzw worin jetzt genau der Unterschied liegt in der Behandlung von SQL Sicht aus.
Danke

gruss marc
Member: filippg
filippg Jun 22, 2009 at 12:45:34 (UTC)
Goto Top
Zitat von @lombaseggel:
Kannst du mir evnt etwas mehr erklären warum das NULL, Probleme
macht/machen kann in deinen Augen?
Ich dachte, das hättest du gerade selber festgestellt.
Fies finde ich etwa:
SELECT * FROM bla WHERE x = 5
Welche Abfrage liefert dann alle anderen Zeilen?
SELECT * FROM bla WHERE x != 5
würde man denken, ist aber natürlich falsch - wenn die Spalte x Null erlaubt.

Grundsätzlich hat man sich eine Bimodale Logik angewöhnt - es gibt TRUE oder FALSE, 0 oder 1, mehr nicht. NULL macht jetzt wieder ein Trimodale Logik daraus, neben True und False ist auf einmal Unknown erlaubt. Und das muss man halt bei jedem Query beachten. Und auch wenn man Funktionen oder gespeicherte Prozeduren nutzt muss man immer erstmal schauen, wie die sich bei NULL verhalten.
Um den Spaß zu erhöhen kann man im SQL-Server verschiedene Settings vornehmen, die das Verhalten (u.a.) bezgl. Null ändern. Damit ist dann z.B. wieder die (nicht ganz unintuitive) Klausel "x = NULL" zulässig, die vorher zwar keinen Syntaxfehler darstellt, aber leider keine Werte liefert.

Gruß

Filipp
Member: Biber
Biber Jun 25, 2009 at 22:28:15 (UTC)
Goto Top
Öhhm, lombaseggel,

wie ist denn der gefühlte Status Deines Beitrags?

Sind noch Fragen offen, kann ein kleiner grüner Haken dran oder muss alles noch etwas reifen?

Gib doch mal Feedback bitte

Danke
Biber
Member: lombaseggel
lombaseggel Jun 26, 2009 at 07:40:29 (UTC)
Goto Top
muss noch etwas "reifen" wir sind leider noch nicht zur Umsetzung gekommen

Danke Gruss Marc