IN-Klausel mit NULL oder IS NULL

83

Postgres ist die Datenbank

Kann ich einen NULL-Wert für eine IN-Klausel verwenden? Beispiel:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

Ich möchte mich auf diese vier Werte beschränken.

Ich habe die obige Anweisung ausprobiert und sie funktioniert nicht. Sie wird ausgeführt, fügt jedoch keine Datensätze mit NULL id_fields hinzu.

Ich habe auch versucht, eine ODER-Bedingung hinzuzufügen, aber dadurch wird die Abfrage ausgeführt und ausgeführt, ohne dass ein Ende in Sicht ist.

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL

Irgendwelche Vorschläge?

Phill Pafford
quelle
10
Eine inAnweisung wird identisch mit analysiert field=val1 or field=val2 or field=val3. Wenn Sie dort eine Null eingeben, läuft es darauf hinaus, field=nullwas nicht funktioniert.
Marc B
1
Die 2. Abfrage sollte richtig sein. Welche anderen Dinge sind in Ihrer whereKlausel?
Daniel A. White
@ Daniel A. White, aktualisiert, um die Abfrage mit mehr Bedingungen
widerzuspiegeln

Antworten:

122

Eine inAnweisung wird identisch mit analysiert field=val1 or field=val2 or field=val3. Wenn Sie dort eine Null eingeben, läuft es darauf hinaus, field=nullwas nicht funktioniert.

( Kommentar von Marc B )

Ich würde das aus Hellsichtigkeit tun

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
Daniel A. White
quelle
Ahh das hat es geschafft, danke! Wenn Sie also die Felder einschließen, werden der WHERE-Klausel beide Bedingungen hinzugefügt. Nur zur Klarstellung
Phill Pafford
1
@Phill - es war ein Problem mit der Reihenfolge der Operationen.
Daniel A. White
20

Ihre Abfrage schlägt aufgrund der Priorität des Operators fehl . ANDbindet vorher OR!
Sie benötigen ein Paar Klammern, was keine Frage der "Klarheit" ist, sondern eine reine logische Notwendigkeit .

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Die hinzugefügten Klammern verhindern die vorherige ANDBindung OR. Wenn es keine anderen WHEREBedingungen ANDgäbe (nein ), würden Sie keine Klammern benötigen . Die akzeptierte Antwort ist in dieser Hinsicht etwas irreführend.

Erwin Brandstetter
quelle
15
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Damit entfernen Sie die Null aus der Prüfung. Bei einem Nullwert in id_field würde die Koaleszenzfunktion anstelle von Null 'unik_null_value' zurückgeben, und durch Hinzufügen von 'unik_null_value zur IN-Liste würde die Abfrage Beiträge zurückgeben, bei denen id_field den Wert 1-3 oder null hat.

Ove Halseth
quelle
2
Eine kleine Erklärung wäre für zukünftige Leser hilfreich. Wie hilft Ihr Code, das Problem zu lösen?
Showdev
9

Die Frage, wie sie von Daniel beantwortet wurde, ist vollkommen in Ordnung. Ich wollte eine Notiz bezüglich NULLS hinterlassen. Wir sollten vorsichtig sein, wenn Sie den Operator NOT IN verwenden, wenn eine Spalte NULL-Werte enthält. Sie erhalten keine Ausgabe, wenn Ihre Spalte NULL-Werte enthält und Sie den Operator NOT IN verwenden. So wird es hier erklärt http://www.oraclebin.com/2013/01/beware-of-nulls.html , ein sehr guter Artikel, auf den ich gestoßen bin und den ich teilen wollte.

Sushant Butta
quelle
Ich bin mir nicht sicher, wie viele Benutzer dieses Problem hatten, aber ich hatte genau dieses Problem beim Mischen von Nullen und dem Operator NOT IN und habe in den letzten zwei Stunden darüber nachgedacht. Dies ist der Täter ...
Govind Rai
1
Der Link ist tot.
Dag Høidahl
1
Ähnliches lebt jetzt.
Immer ein Lernender
3

Hinweis: Da jemand behauptet hat, der externe Link sei in Sushant Buttas Antwort tot , habe ich den Inhalt hier als separate Antwort veröffentlicht.

Vorsicht vor Nullen .

Heute bin ich bei der Verwendung von IN und NOT INOperatoren auf ein sehr seltsames Abfrageverhalten gestoßen . Eigentlich wollte ich zwei Tabellen vergleichen und herausfinden, ob ein Wert von in table bexistiert table aoder nicht, und sein Verhalten herausfinden, wenn die Spalte nullWerte enthält . Also habe ich gerade eine Umgebung erstellt, um dieses Verhalten zu testen.

Wir werden eine Tabelle erstellen table_a.

SQL> create table table_a ( a number);
Table created.

Wir werden eine Tabelle erstellen table_b.

SQL> create table table_b ( b number);
Table created.

Fügen Sie einige Werte in ein table_a.

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.

Fügen Sie einige Werte in ein table_b.

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.

Jetzt führen wir eine Abfrage aus, um die Existenz eines Werts zu überprüfen, table_aindem wir dessen Wert table_banhand des INOperators überprüfen .

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

Führen Sie die folgende Abfrage aus, um die Nichtexistenz zu überprüfen.

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2

Die Ausgabe kam wie erwartet. Jetzt fügen wir einen nullWert in die Tabelle ein table_bund sehen, wie sich die beiden obigen Abfragen verhalten.

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected

Die erste Abfrage hat sich wie erwartet verhalten, aber was ist mit der zweiten Abfrage passiert? Warum haben wir keine Ausgabe bekommen, was hätte passieren sollen? Gibt es einen Unterschied in der Abfrage? Nein .

Die Änderung ist in den Daten der Tabelle table_b. Wir haben einen nullWert in die Tabelle eingefügt. Aber warum verhält es sich so? Lassen Sie uns die beiden Abfragen in "AND"und "OR"Operator aufteilen .

Erste Abfrage:

Die erste Abfrage wird intern in etwa so behandelt. A nullwird hier also kein Problem verursachen, da meine ersten beiden Operanden entweder nach trueoder auswerten false. Aber mein dritter Operand a = nullwird weder bewerten truenoch false. Es wird nur ausgewertet null.

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null

Zweite Abfrage:

Die zweite Abfrage wird wie folgt behandelt. Da wir einen "AND"Operator verwenden und alles andere als truein einem der Operanden, wird mir keine Ausgabe gegeben.

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null

Wie gehen wir damit um? Wir werden alle not nullWerte aus der Tabelle auswählen, table_bwährend wir den NOT INOperator verwenden.

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2

Seien Sie also immer vorsichtig mit den NULLWerten in der Spalte, wenn Sie den NOT INOperator verwenden.

Vorsicht vor NULL !!

1000111
quelle
Hervorragende Antwort. Ich habe gerade das Problem in meiner Arbeit entdeckt. Sehr sehr seltsames Verhalten von Oracle.
Oputyk
0

Ich weiß, dass die Antwort zu spät ist, aber für andere nützlich sein könnte. Sie können eine Unterabfrage verwenden und die Null in 0 konvertieren

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)
ch2o
quelle
Dies ähnelt der Antwort von Ove Halseth mit Coalesce.
user890332
0

Nullbezieht sich auf ein Fehlen von Daten. Nullwird formal als ein Wert definiert, der nicht verfügbar, nicht zugewiesen, unbekannt oder nicht anwendbar ist (OCA Oracle Database 12c, SQL Fundamentals I-Prüfungshandbuch, S. 87). Daher werden möglicherweise keine Datensätze mit Spalten angezeigt, die Nullwerte enthalten, wenn diese Spalten mithilfe einer "in" - oder "not in" -Klausel eingeschränkt werden.

Roger Rowe
quelle