wake-up-neo.com

Oracle/PL SQL/SQL-Nullvergleich in where-Klausel

Nur eine Frage zum Umgang mit Werten führt zu Nullwerten in einer Abfrage.

Zum Beispiel habe ich die folgende Tabelle mit den folgenden Feldern und Werten

TABLEX
Column1
1        
2        
3      
4        
5      
---------
Column2
null
A
B
C
null

Ich übergebe eine VariableY für eine bestimmte Prozedur. Innerhalb der Prozedur befindet sich ein solcher Cursor

CURSOR c_results IS
SELECT * FROM TABLEX where column2 = variableY

jetzt ist das Problem variabelY kann entweder Null, A, B oder C sein. Wenn die VariableY Null ist, möchte ich alle Datensätze auswählen, bei denen Spalte2 Null ist, andernfalls ist Spalte2 entweder A, B oder C.

Ich kann den obigen Cursor/die Abfrage nicht ausführen, da VariableY nicht gleich Null ist, weil der Vergleich durchgeführt werden sollte

CURSOR c_results IS
SELECT * FROM TABLEX where column2 IS NULL

Welchen Cursor/welche Abfrage sollte ich verwenden, der entweder eine Null- oder eine String-Variable enthält?.

Sorry, wenn meine Frage etwas verwirrend ist. Ich kann Dinge nicht so gut erklären. Danke im Voraus.

18
user2447740

Erzeugen Sie je nach Inhalt dieses Parameters unterschiedliche SQL-Werte oder ändern Sie Ihre SQL-Einstellungen folgendermaßen:

WHERE (column2 = variableY) OR (variableY IS NULL AND column2 IS NULL)

Ask Tom von Oracle sagt:

where decode( col1, col2, 1, 0 ) = 0  -- finds differences

oder

where decode( col1, col2, 1, 0 ) = 1  -- finds sameness - even if both NULL

Sicheres Vergleichen von NULL-Spalten als gleichwertig

6
rghome

Die folgende Antwort ähnelt der Antwort "oben", ist jedoch präziser:

WHERE ((column2 = variableY ) or COALESCE( column2, variableY) IS NULL)

2
drjumper

Sie könnten so etwas verwenden:

SELECT * FROM TABLEX WHERE COALESCE(column2, '') = COALESCE(variableY, '')

(COALESCE nimmt den ersten Nicht-NULL-Wert an)

Beachten Sie, dass dies nur funktioniert, wenn der Spalteninhalt nicht '' (leere Zeichenfolge) ist. Andernfalls schlägt diese Anweisung fehl, da NULL mit '' (leerer String) übereinstimmt.

(edit) Sie könnten auch Folgendes in Betracht ziehen:

SELECT * FROM TABLEX WHERE COALESCE(column2, 'a string that never occurs') = COALESCE(variableY, 'a string that never occurs')

Damit wird die Fail-Hypothese behoben.

2
Stef Heyenrath

Abhängig von den Daten, die Sie betrachten, ist dies möglicherweise nicht angemessen, aber ein Trick, den ich gesehen (und verwendet) habe, ist der Vergleich von NVL (Feldname, Somenonexistentvalue). 

Wenn AGE beispielsweise eine optionale Spalte ist, können Sie Folgendes verwenden:

if nvl(table1.AGE,-1) = nvl(table2.AGE,-1)

Dies setzt voraus, dass es einen Wert gibt, den Sie know niemals zulassen werden. Das Alter ist ein gutes Beispiel, Gehalt, Sequenznummern und andere Zahlen, die nicht negativ sein können. Strings können natürlich komplizierter sein - Sie können sagen, dass Sie niemals jemanden namens "xyzzymaryhadalittlelamb" oder ähnliches haben werden, aber an dem Tag, an dem Sie mit dieser Annahme laufen, wissen Sie, dass sie jemanden mit diesem Namen einstellen !!

Alles, was gesagt wurde: "wo a = b oder (a ist null und b ist null)" ist der traditionelle Weg, es zu lösen. Das ist bedauerlich, da selbst erfahrene Programmierer diesen Teil manchmal vergessen. 

1
JOATMON

Sie könnten DUMP verwenden:

SELECT * 
FROM TABLEX 
WHERE DUMP(column2) = DUMP(variableY);

DBFiddle Demo

Warnung: Dies ist kein SARG-fähiger Ausdruck, daher gibt es keine Indexverwendung.

Bei diesem Ansatz müssen Sie nicht nach Werten suchen, die in Ihren Daten nicht vorhanden sind (wie NVL/COALESCE).

0
Lukasz Szozda

Versuchen Sie es mit der Funktion ISNULL(). Sie können überprüfen, ob die Variable NULL ist. Wenn ja, legen Sie einen Standardrückgabewert fest. Campern von Null auf Null ist nicht wirklich möglich. Denken Sie daran: null <> null

0
karel
WHERE variableY is null or column2 = variableY 

for example:
create table t_abc (
id number(19) not null,
name varchar(20)
);

insert into t_abc(id, name) values (1, 'name');
insert into t_abc(id, name) values (2, null);
commit;

select * from t_abc where null is null or name = null;
--get all records

select * from t_abc where 'name' is null or name = 'name';
--get one record with name = 'name'
0
Kevin