SQL = und <> (Mysql)

derocco

Lt. Junior Grade
Registriert
Nov. 2015
Beiträge
337
Tabelle mit 60 Einträgen. 20 Davon haben ein Storno - Flag

select * from handle where storno = 'x'; -> Resultat 40 Rows
select * from handle where storno <> 'x'; -> Resultat 0 Rows (!)

Select * from handle where storno is null; -> Resultat 20 Rows

Warum funktioniert das nicht mit <> ?
Ich Habe auch != versucht. eben so mit double quotes...

Wo ist der Fehler?
 
Was nutzt du als mysql server und in welcher version?
Steht in den feldern ohne flag etwas?
 
Zuletzt bearbeitet:
Null hat keinen Wert, somit kann auch <>/!= nicht verwendet werden da kein Wert gefunden werden kann.

Würdest du aber statt null in der Tabelle ein '' (leeren string) einfügen damit es kein null wert ist, dann könntest auch wieder mit <> 'x' diese filtern.
 
falsch gelesen...
 
kartoffelpü schrieb:
Ich würde "storno" von String auf bool umstellen
ggf kommt da auch mal noch was snderes rein als x
Aktuell ist es Varchar 8

Variable_name Value
----------------------- -----------------------
innodb_version 5.7.32
protocol_version 10
slave_type_conversions
tls_version TLSv1,TLSv1.1,TLSv1.2
version 5.7.32-0ubuntu0.16.04.1
version_comment (Ubuntu)
version_compile_machine x86_64
version_compile_os Linux
 
Code:
SELECT NULL = NULL; 
SELECT NULL != NULL;
SELECT NULL IS NULL;
SELECT NULL IS NOT NULL;
NULL-Handling bei Datenbanken ist total beschissen, ja. Deswegen versucht man es zu umgehen, wo es möglich ist. Deine Abfrage muss halt jedes mal auf den Wert prüfen und zusätzlich NULL-Checks durchführen. Ist halt so.

Nutz lieber dedizierte Flags (bool/tinyint) für sowas.
Code:
WHERE ist_storniert = 1
Wenn du das nicht selbst festlegen kannst, bleibt dir aber nichts Anderes übrig als die Checks zu machen.
 
  • Gefällt mir
Reaktionen: Arc Angeling und Tornhoof
  • 20 Einträge haben keinen Storno-Flag, da bei diesen ein null hinterleg ist
  • Wenn du weder mit bool noch mit null arbeiten willst benutze enum oder fest definiere Werte (0, 1, 2, 3 etc.)

Ansonsten hat dir Jokerboy erklärt, wieso die Ausgabe von mysql korrekt ist.
 
innodb = MariaDB / MySQL : https://mariadb.com/kb/en/null-safe-equal/

via: Syntaxunterschiede SQL

Eine Google-Anfrage nach dem Operator liefert zB eine Microsoft Hilfsseite auf der zB "SET ANSI_NULLS (Transact-SQL)" erwähnt wird.
Gibt an, dass sich die Vergleichsoperatoren Gleich (=) und Ungleich (<>) bei Verwendung mit NULL-Werten in SQL Server 2019 (15.x) ISO-konform verhalten müssen.
Q: https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql
 
Jokeboy schrieb:
Null hat keinen Wert, somit kann auch <>/!= nicht verwendet werden da kein Wert gefunden werden kann.

Würdest du aber statt null in der Tabelle ein '' (leeren string) einfügen damit es kein null wert ist, dann könntest auch wieder mit <> 'x' diese filtern.
Man kann auch anders formulieren, dass jeglicher Vergleich mit NULL (ausser der mit IS NULL) immer zu false wird.

Der leere String ist in manchen Datenbanken (z.B. Oracle Database) aber leider auch eine Falle, weil er dann als NULL in das Feld eingetragen wird. Da muss man wirklich extrem aufpassen.
 
derocco schrieb:
Tabelle mit 60 Einträgen. 20 Davon haben ein Storno - Flag

select * from handle where storno = 'x'; -> Resultat 40 Rows
select * from handle where storno <> 'x'; -> Resultat 0 Rows (!)

Select * from handle where storno is null; -> Resultat 20 Rows

Warum funktioniert das nicht mit <> ?
Ich Habe auch != versucht. eben so mit double quotes...

Wo ist der Fehler?

Es ist so wie Vorposter sagen. NULL ist nur mit "IS NULL" bzw. "IS NOT NULL" abzufragen.

Die Frage ist eher, wie Du diesen Flag in der Datenbank möglichst eindeutig abbilden willst.
Das kann später zu Verwirrung führen, wenn "<> 'x'" nicht das intuitiv erwartete Ergebnis liefert.

Welche Wert kann "Storno" den annehmen?
--> Bei Ja/Nein wäre ein einfaches 0/1 (tinyint) wie vorgeschlagen eine einfache Lösung, dann kannst Du "0" einfach als Default-Wert in der Tabellenspezifikation festlegen
--> Falls es mehrere "Zustände" gibt, wäre eventuell der Typ ENUM oder SET für Dich interessant.
 
Wenn du ausschließen kannst, dass in der Spalte ein bestimmter Wert stehen kann (z.B. ein leerer String):

IFNULL(storno, '') <> 'x'

disclaimer: nicht toll, wenn du den Index auf die Spalte brauchst, aber für kleinere Tabellen null Problemo.
 
NULL sollte man nur im Ausnahmefall als Wert für ein Feld zulassen, wenn es wirklich nicht anders möglich ist, da es immer fehleranfällig ist (wie man sieht).
Für das varchar-Storno-Feld, auch wenn ich mir nicht vorstellen kann, warum das nicht binär sein soll, würde ich dann halt für nicht stornierte Einträge ein N setzen oder so. Aber besser wäre es daraus den Typ Bit zu machen. Storniert ja/nein ist ja eigentlich ein binärer Zustand. Will man mehr Informationen dazu transportieren wird ein Storno eh eine eigene Entität und man trägt dann nur den Fremdschlüssel entsprechend ein.
 
Ähm, wenn es Weißnicht geben muss, dann muss es das geben. Null ist nicht fehleranfällig. Man muss nur damit umgehen können.

ich stelle allerdings durchaus auch die Frage in den Raum, ob “keine Ahnung ob storniert wurde“ eine zulässig Option sein kann oder darf oder sollte.

In keinem Fall ist NULL synonym zu False. Es heißt nur “unbekannt”, “unbestimmbar“, “keine Angabe“. Eben so, wenn ich den namen nicht kenne... oder nicht weiß ob ich ja oder nein angeben soll.
 
  • Gefällt mir
Reaktionen: mental.dIseASe, GroMag und Arc Angeling
Ich würde NULL nicht pauschal verteufeln, aber es ist schon richtig das man eher "NOT NULL" als Default nehmen sollte solange es keinen Grund gibt NULL zuzulassen. Aber am Ende muss man einfach ein paar Grundlagen zu NULL lernen wenn man eine relationale Datenbank benutzt, es ist ein wichtiges Konzept um das man nicht drumherum kommt.

Bei so einer Flag würde ich aber fast immer sagen das man kein NULL zulassen sollte. Entweder es wurde storniert und soll so behandelt werden, oder es wurde nicht storniert. Die Anwesenheit von NULL macht keinen Sinn für mich hier, diese Information darf eigentlich nicht unbekannt sein. Wenn es korrekt ist das alle NULL als False behandelt werden sollen, dann würde ich die alle in der DB auf False setzen und dann die Spalte als "NOT NULL" definieren.
 
RalphS schrieb:
Ähm, wenn es Weißnicht geben muss, dann muss es das geben. Null ist nicht fehleranfällig. Man muss nur damit umgehen können.
Ich habe nichts anderes geschrieben (NULL nur in Ausnahmefällen) bis auf das die Verwendung von NULL auch fehleranfällig ist. Da sieht man hier im Thread ja ganz deutlich, dass man damit schnell Fehler verursachen kann. Man muss sich immer "speziell" darum kümmern und das ist eben anfällig für Fehler, die man dabei schnell mal machen kann. Deswegen und weil es einfach ein Zeichen für einen schlechten Stil ist, sollte man es wo auch immer es geht vermeiden. Wenn ich ein varchar-Storno-Feld sehe, wo NULL und X eingetragen wird, sehe ich mit meinen professionellen Blick, dass sich da niemand wirklich mal Gedanken um sein Datenmodell gemacht hat. Ob etwas storniert ist, kann in einen Geschäftsprozess ja nicht unbekannt sein. Entweder etwas ist storniert oder etwas ist nicht storniert. Das ist ja keine Quantenmechanik.
 
  • Gefällt mir
Reaktionen: Dalek und RalphS
@ayngush
In diesem Fall wurde einfach ein falscher Datentyp verwendet, was genau hat das mit NULL zu tun?
"Ausnahmefälle" und "Fehleranfälligkeit" sind zwei Quatschaussagen. Jede halbwegs komplexe SQL-Datenbank nutzt nullable-Felder, das ist weder falsch noch werden dadurch Fehler produziert. Ist ein integer jetzt auch schlecht, weil man nicht einfach einen varchar reinschreiben kann? Wer zu unerfahren ist, das zu verwenden, produziert an allen möglichen Stellen Fehler.
 
Du differenzierst es ja schon falsch aus: Ein Datenmodell hat Datentypen und das nicht ohne Grund.
NULL ist einfach nichts und in den aller meisten Fällen auch vermeidbar, wenn man sich mal hinsetzt und etwas genauer über sein Datenmodell nachdenkt und dabei auch die 3NF berücksichtigt.

Dann kommt man schnell zu dem Schluss, dass es so etwas wie "weiß nicht" wirklich nur in Ausnahmefällen gibt, denn meistens ist ein "weiß nicht" dann einfach kein Eintrag einer Entität und nicht ein NULL-fähiges Attribut.

Edit: Dazu kommt, dass SQL halt eine 3-Werte-Logik kennt. Wahr, falsch, unbekannt. NULL ist dieses unbekannt. Jetzt ist X = X also weder wahr noch falsch wenn X den Wert NULL hat ist der Zustand Unbekannt und kann mit diesen Operatoren nicht abgefragt werden. Mit einer entsprechenden Konfiguration kann X > X dann jedoch wahr sein, wenn X NULL wäre. Das sieht man aber erst auf den zweiten und dritten Blick. Mag ja für Leute, die Datenbankdesidgner, Entwickler, Admin und weiß der Kukckuk in Personalunion sind kein Problem darstellen - es soll aber Firmen geben, da richten die Fachanwendungsentwickler nicht die Datenbank auf den Server ein...
Das und viele weitere Fehler, die sich dann von der Datenbank in die Anwendungen ziehen, wie zum Beispiel, dass viele Programmiersprachen den Wert NULL nicht kennen und dann irgendwas interpretieren, Beispielsweise Interger NULL wird dann zu einer 0 interpretiert - was Logisch jedoch falsch ist usw. führt dazu, dass man NULL einfach wirklich nur für die unvermeidbaren Ausnahmen, die es gibt (Geburtsdatum bei Juristischen Personen z.B.) verwenden sollte - und wo immer es geht einfach nochmal ein Zweites Mal Nachdenken, bevor man ein Attribut als "NULLable" festlegt.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: BeBur
Schon die Mannigfaltigkeit der möglichen Interpretationen die hier ja zum Teil auch genannt worden ist zeigt auch das Problem. Kann stehen für: "unbekannt", "nicht bestimmbar", "Fehler", "nicht vorhanden"
Eine Spalte "Flag" klingt jedenfalls nach etwas, das NOT NULL sein sollte.
 
NULL ist nicht "unbekannt" oder "weiß nicht".
Es bedeutet, dass der Wert nicht gesetzt ist und nichts anderes. Ähnlich wie in Programmiersprachen, daher wird das von ORM-Systemen auch genauso übersetzt. Auch in der Programmiersprache muss ich darauf achten, dass ein Wert u.U. null sein kann.

Einfaches Beispiel: Ich habe eine Entität, in der bestimmte Eigenschaften sagen wir mal 10 Comboboxen im UI widerspiegeln. Die können leer sein oder man wählt halt was aus.
Wenn mir die Leute für jede 1:1-Relation extra Tabellen anlegen, in diesem Fall also 10 Stück zusätzlich zu den 10, die die Comboboxinhalte enthalten, nur um nicht NULL reinschreiben zu müssen, wenn die Eigenschaft nicht gesetzt ist, würde ihnen aufs Dach steigen. Das hat nichts mit 3NF zu tun, nach der Normalisierung ist beides möglich. Nur wenn ich noch 5 andere Entitäten haben, die die 10 Eigenschaften ebenfalls enthalten, bekomme ich 50 zusätzliche Tabellen, um NULLs zum umgehen. Ziemlich schwachsinniges Design, meiner Meinung nach.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: RalphS
Ein Wert kann nicht NULL sein; NULL ist ein Zustand und kein Wert. Ein Wert kann also höchstens den Zustand NULL haben.

Eine nicht gewählte Option einer Werteliste spiegelt ja genau das Dilemma wieder: Einige Frontends übermitteln für eine nicht gewählte Option dann einfach einen leeren String oder einen Index -1 oder einen Index 0 oder einfach den Wert der ersten Option der Werteliste oder einen zuvor festgelegten Default-Wert andere Frontends übermitteln das gesamte Werteliste-Element überhaupt nicht mehr im Datensatz mit, es fehlt dann vollständig usw.

HTML zum Beispiel handhabt das so (inkonsequent): Ist das Select-Element mit den Attribut size=1 versehen, dann wird die Erste Option der Liste übermittelt, wenn der Benutzer nichts explizit ausgewählt hat und kein "selected" Attribut bei einen Option-Element der Liste vorhanden ist.
Hat das Select-Element jedoch das Attribut size=2 oder größer und der Benutzer wählt keinen Eintrag aus, dann wird das gesamte Select-Element im Datensatz nicht mehr übermittelt.

Abgesehen von den anderen Problemen, wie dass NULL nicht in einen Binärbaum indizierbar ist. Die Datenbanken unterschiedliches Verhalten beim Zählen COUNT(Attribut) von NULL-Attribten haben (einige zählen NULL-Einträge mit, andere nicht) Oracle schert aus und lässt X = NULL zu, da es NULL als '' (Leerstring) interpretiert obwohl das gegen den ANSI-SQL Standard verstößt und gegen die ternäre Logik verstößt usw.

Ich würde NULL halt vermeiden, wo immer es sinnvoll möglich ist.
 
Zurück
Oben