![]() |
Datenbank: Firebird • Version: 3.0 • Zugriff über: FIREDAC
Im Select null oder Wert in WHERE
Hallo Zusammen,
ich importiere Adressen in einer Tabelle. Jetzt kann es vorkommen dass die Felder Strasse, PLZ und Ort leer sind also wird in der Tabelle NULL geschrieben wird. Beim importieren kann die erste Adresse keine Strasse haben die zwei keine PLZ die dritte komplett ohne Adresse. Sie darf natürlich nur einmal importiert werden. Also muss ich jedes Feld dynamisch gegen ein Wert oder gegen Null prüfen. Eine Möglichkeit ist über Macros zu arbeiten.
Code:
Gibt es keine elegantere Methode?
SELECT ADRESSID
FROM ADRESSEN WHERE VORNAME = :VORNAME AND NACHNAME = :NACHNAME AND STRASSE = :STRASSE AND PLZ = :PLZ AND ORT = :ORT Dieses Statement müsse sich jetzt dynamisch z.B.: über Macros ändern z.B.: SELECT ADRESSID FROM ADRESSEN WHERE VORNAME = :VORNAME AND NACHNAME = :NACHNAME !strasseMacro !plzMacro !OrtMacro if quelle.Strasse='' then MacroByName('strasseMacro').AsRaw = 'AND STRASSE IS NULL' else MacroByName('strasseMacro').AsRaw = 'AND STRASSE = :STRASSE'; Gruß Kostas |
AW: Im Select null oder Wert in WHERE
Was du im Delphi machst, das kann man auch im SQL machen. :zwinker:
z.B. (das IF als IIF, IFTHEN, CASE oder wie auch immer)
SQL-Code:
AND IIF(:STRASSE IS NULL, STRASSE IS NULL, STRASSE = :STRASSE)
bzw. da du ja kein NULL, sondern einen Leerstring in der Variable/Parameter hast
SQL-Code:
AND IIF(:STRASSE = '', STRASSE IS NULL, STRASSE = :STRASSE)
oder sicherheitshalber, falls doch
SQL-Code:
AND IIF(COALESCE(:STRASSE, '') = '', STRASSE IS NULL, STRASSE = :STRASSE)
SQL-Code:
AND IIF(NULLIF(:STRASSE, '') IS NULL, STRASSE IS NULL, STRASSE = :STRASSE)
oder
SQL-Code:
AND ((STRASSE IS NULL AND :STRASSE IS NULL) OR STRASSE = :STRASSE)
SQL-Code:
AND ((STRASSE IS NULL AND NULLIF(:STRASSE, '') IS NULL) OR STRASSE = :STRASSE) -- wieder das wegen '' oder NULL
oder
SQL-Code:
AND COALESCE(STRASSE, :STRASSE) = :STRASSE -- bzw. wegen dem '' oder NULL hier im Delphi als Text oder NULL übergeben
SQL-Code:
AND COALESCE(STRASSE, NULLIF(:STRASSE, '')) IS NOT DISTINCT FROM NULLIF(:STRASSE, '') -- wieder '' oder NULL
SQL-Code:
AND COALESCE(STRASSE, :STRASSE, '') = COALESCE(:STRASSE, '') -- oder andersrum
|
AW: Im Select null oder Wert in WHERE
Hallo himitsu,
ja das ist voll Krank nur weil das SQL damals nicht sauber umgesetzt wurde. Warum wurde der Vergleich auf NULL anders behandelt als der Vergleich mit einem Wert:
Code:
Was mich auch ärgert:
(AND STRASSE = NULL) (AND STRASSE = 'Bahnhofstasse 1')
Eigentlich müsste das SQL so sein:
Code:
C# hat das in LINQ versucht besser zu lösen.
FROM ADRESSEN
SELECT NAME, VORNAME WHERE NAME = :NAME Gruß Kostas |
AW: Im Select null oder Wert in WHERE
Nja, sauber oder nicht, das ist so eine Sache ... irgendwas mit NULL ergibt halt NULL, außer beim OR.
Und das ist eigentlich in allen Datenbanksprachen einheitlich so. Drum gibt es ja so Dinge wie COALESCE, CONCAT (statt dem || ), NULLIF, IS DISTINCT FROM, IS NOT DISTINCT FROM usw. z.B.
SQL-Code:
heißt im Postgres so, aber gibt gibt es auch in anderen Sprachen (auch wenn es dort vielleicht anders heißt).
IS [NOT] DISTINCT FROM
Es vergleicht beide Seiten auf Identisch, und kann auch mit NULL vergleichen, ohne dass dabei NULL raus kommt. |
AW: Im Select null oder Wert in WHERE
In so manchem DBMS kann man Operatoren auch selbst definieren.
Dort könnteste du dir dann auch einen "kurzen" Operator für Vergleiche mit NULL und EMPTY selbst bauen, wenn/da es sowas oft nicht "vernünftig" gibt, denn mal ganz im Ernst, aber wer sich
SQL-Code:
ausgedacht hat ... k.A. was der da geraucht hatte.
IS NOT DISTINCT FROM
SQL-Code:
CREATE OR REPLACE FUNCTION compare_with_null(value_a anyelement, value_b anyelement) RETURNS boolean AS $$
SELECT nullif(value_a, '') = nullif(value_b, '') $$ LANGUAGE SQL IMMUTABLE; CREATE OPERATOR ~= (LEFTARG=anyelement, RIGHTARG=anyelement, PROCEDURE=compare_with_null); SELECT ADRESSID FROM ADRESSEN WHERE VORNAME = :VORNAME AND NACHNAME = :NACHNAME AND STRASSE ~= :STRASSE AND PLZ ~= :PLZ AND ORT ~= :ORT |
AW: Im Select null oder Wert in WHERE
SQL gibt es ja schon sehr lange. Warum bestimmte Sachen nicht verbessert werden ist schon komisch.
In meinen Fall funktioniert das nicht wenn ich auch nach einem NULL prüfen muss :
Code:
und ich muss es so schreiben:
AND (STRASSE = :STRASSE)
Code:
AND ((STRASSE IS NULL AND :STRASSE IS NULL) OR (STRASSE = :STRASSE))
|
AW: Im Select null oder Wert in WHERE
Zitat:
ja, da gibt es einiges. :lol: so bleibt es nicht langweilig. |
AW: Im Select null oder Wert in WHERE
Zitat:
z.B. siehe die Varianten nach dem letzten "oder". :zwinker: Das Erste davon mit NULL im Delphi abgefangen und das Letzte davon im SQL behandelt.
Delphi-Quellcode:
// im Delphi
if quelle.Strasse='' then ParamByName('strasse').Clear //ParamByName('strasse').AsValue = Null else ParamByName('strasse').AsString = quelle.Strasse; |
AW: Im Select null oder Wert in WHERE
Es ist schon ungewöhnlich, wenn ein Textfeld wie "Strasse" mit NULL initialisiert wird, da Wert nicht vorhanden recht gut mit einem Leerstring widergegeben werden kann. Anders ist es bei numerischen oder Datumswerten da wird ein NULL hierfür benötigt.
Gruß K-H |
AW: Im Select null oder Wert in WHERE
Zitat:
|
AW: Im Select null oder Wert in WHERE
Zitat:
Adresse = 'XY' Adresse = null Adresse is null warum wurde hier "is" und nicht "=" implementiert. Also Adresse = null. Damit hätte man nur ein Variante des Vergleichs. Durch die Fallunterscheidung muss man daran denken dass auch gegen null verglichen werden könnten und müsste das SQL anpassen wie auch vom himitsu vorgeschlagen z.B.: ((STRASSE IS NULL AND :STRASSE IS NULL) OR (STRASSE = :STRASSE)) oder über Macros das SQL dynamisch aufbauen. Ist meiner Meinung nach völlig unnötig. Denn wenn man nicht daran denkt, funktioniert der Vergleich nicht!
Code:
SELECT ADRESSID
FROM ADRESSEN WHERE VORNAME = :VORNAME AND NACHNAME = :NACHNAME AND STRASSE = :STRASSE AND PLZ = :PLZ AND ORT = :ORT if mdQuelle.FieldByName('STRASSE').IsNull then qrZiel.ParamByName('STRASSE').Clear else qrZiel.ParamByName('STRASSE').AsString := mdQuelle.FieldByName('STRASSE').AsString; Gruß Kostas |
AW: Im Select null oder Wert in WHERE
Zitat:
ich bekommen eine DB mit mehreren tausend Adressen. Einige Felder davon sind nullable und sind auch leer. Ich würde die Strings übrigens auch auf null lassen und nicht mit einem leer String befüllen, einfach nur weil ich es als richtiger empfinde. Aber wie du schon gelesen hast, kritisiere ich NUR die Umsetzung mit dem Unterschied der Abfrage mit "=" für Werte und die Abfrage mit "is" für null. Das finde ich völlig unnötig und eine große Fehlerquelle. Gruß Kostas |
AW: Im Select null oder Wert in WHERE
Es lassen sich bestimmt bessere Erklärungen für das "Warum" finden, aber das war auf die Schnelle:
![]() |
AW: Im Select null oder Wert in WHERE
Ich denke über die IS NULL Prüfungen nicht mehr nach.
Vielleicht ist das auch bei den Leuten in den Standardisierungsgremien so. Vielleicht ist es aber auch einfach eine Riesenkatastrophe, wenn das mal abgeändert würde. Immerhin, es gibt noch andere Stellen, die man vielleicht kennen sollte. Z.B. die Handhabung von Leerstrings in Oracle, dort wird NULL daraus gemacht. Delphi "kennt" das aber, auch interessant. An dem Beispiel im Stackoverflow Link von Jumpy kann man eigentlich ganz schön sehen, welchen Hintergrund Nullwerte bspw. bei Outerjoins haben. Wenn durch einen Outerjoin leere Textspalten also NULL Werte "entstehen", kann man wirklich nicht sagen, dass es das gleiche ist, wie ein Leerstring. Eine andere Perspektive wäre die Frage, wie werden eigentlich schon im Programm (im Memory) Variablen initialisiert (oder auch nicht) und welchen Wert haben nicht initialisierte Variablen? Hier ist noch ein Artikel mit ein paar weiterführenden Links (nicht nur zu NULL): ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz