sql >> Database teknologi >  >> RDS >> Oracle

IKKE I valg med NULL-værdier

Først lidt teori:Null (SQL)

De vigtigste dele for os fra ovenstående link:

Sammenligninger med NULL og logikken med tre værdier (3VL)

Da Null ikke er medlem af noget datadomæne, betragtes det ikke som en "værdi", men snarere en markør (eller pladsholder), der angiver fraværet af værdi. På grund af dette kan sammenligninger med Null aldrig resultere i hverken Sand eller Falsk, men altid i et tredje logisk resultat, Ukendt.[8] Det logiske resultat af udtrykket nedenfor, som sammenligner værdien 10 med Null, er ukendt:

SELECT 10 = NULL       -- Results in Unknown
 

så begge sammenligninger:x = NULL og x <> NULL evalueres til NULL(ukendt).

SQL implementerer tre logiske resultater, så SQL-implementeringer skal sørge for en specialiseret logik med tre værdier (3VL). Reglerne for SQL-logik med tre værdier er vist i tabellerne nedenfor (p ogq repræsenterer logiske tilstande)"[9] Sandhedstabellerne SQL bruger til OG, ELLER og IKKE svarer til et fælles fragment af Kleene- og Łukasiewicz-logikken med tre værdier ( som adskiller sig i deres definition af implikation, men SQL definerer ingen sådan operation).

+---------+-------------+-------------+-------------+-----------+--------+ | p | q | p OR q | p AND q | p = q |p != q | +---------+-------------+-------------+-------------+-----------+--------+ | True | True | True | True | True | False | | True | False | True | False | False | True | | True | Unknown | True | Unknown | Unknown | Unknown| | False | True | True | False | False | True | | False | False | False | False | True | False | | False | Unknown | Unknown | False | Unknown | Unknown| | Unknown | True | True | Unknown | Unknown | Unknown| | Unknown | False | Unknown | False | Unknown | Unknown| | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown| +---------+-------------+-------------+-------------+-----------+--------+

Effekt af Ukendt i WHERE-sætninger

SQL-logik med tre værdier støder på i Data Manipulation Language (DML) i sammenligningsprædikater for DML-sætninger og forespørgsler. WHERE-sætningen får DML-sætningen til kun at virke på de rækker, som prædikatet evaluerer til True.

Så kort sagt:WHERE-klausulen behandler NULL som FALSE

Overvej nu en enklere sag:

SELECT * FROM T1;

|      X |
|--------|
|      1 |
| (null) |
 

og en forespørgsel:

SELECT * FROM t1 WHERE x IN (1, NULL);
 

Ovenstående forespørgsel er en shortland til denne:

SELECT * FROM t1 
WHERE x = 1
  OR  x = NULL
 

For den anden række fra tabel t ( x =NULL) denne betingelse ser sådan ud:

WHERE NULL = 1
   OR NULL = NULL
 

så denne betingelse for rækken x=NULL evalueres til NULL fordi NULL=1 er NULL, NULL=NULL er NULL og NULL OR NULL er også NULL (se venligst tabel 3VL ovenfor).

Overvej nu mere nysgerrig sag:

SELECT * FROM t1 WHERE x NOT IN (1, NULL);
 

Denne klausul x NOT IN (1, NULL) svarer til NOT ( x IN (1, NULL) )
så det svarer også til:

NOT (
  x = 1
  OR
  x = NULL
)
 

og ifølge De Morgans love svarer det til:

NOT ( x = 1 ) AND NOT ( x = NULL )
 

og (hvis vi erstatter NOT x = y med x <> y ) det svarer også til:

 x <> 1 AND x <> NULL
 

Se nærmere på den sidste betingelse:

WHERE 
x <> 1 AND x <> NULL
 

Vi kender mere end x <> NULL evalueres altid til NULL. Vi ved også fra 3VL-tabellen ovenfor, at både true AND NULL er NULL og false AND NULL evalueres til FALSK, så hele betingelsen evalueres altid enten til FALSK eller NULL, men den evalueres aldrig til SAND.

Derfor en forespørgsel med denne betingelse:

SELECT .....
WHERE x NOT IN ( NULL, whatever)
 

giver altid tomme resultater

Og nu din forespørgsel, som også er nysgerrig:

SELECT * FROM t1
WHERE (id, val) NOT IN (select id, val from data2);
 

som kan omskrives (ved hjælp af konstante værdier) til:

SELECT * FROM t1
WHERE (id, val) NOT IN (
       (1, null),
       (2, 2 )
)
 

Denne forespørgsel bruger det såkaldte rækkeværdiudtryk

Dybest set en betingelse, der bruger rækkeværdien som dette

(a, b) = (x, y)
 

svarer til denne:

a = x AND b = y
 

så ovenstående forespørgsel kan omskrives til denne:

SELECT * FROM t1
WHERE NOT (
   id = 1 AND val = NULL
   OR
   id = 2 AND val = 2
)
 

Ifølge De Morgans love er dette identisk med:

SELECT * FROM t1
WHERE 
   NOT ( id = 1 AND val = NULL )
   AND
   NOT ( id = 2 AND val = 2 )
 

og videre til:

SELECT * FROM t1
WHERE 
   ( id <> 1 OR val <> NULL )
   AND
   ( id <> 2 OR val <> 2 )
 

Siden den første del ( id <> 1 OR val <> NULL ) af betingelsen evalueres kun til sand i et tilfælde, hvor id <> 1 (se venligst 3VL-tabellen ovenfor), denne betingelse kan forenkles til:

SELECT * FROM t1
WHERE 
   ( id <> 1 )
   AND
   ( id <> 2 OR val <> 2 )
 

og videre (ifølge De Morgans love) til:

SELECT * FROM t1
WHERE 
   id <> 1 AND id <> 2
   OR
   id <> 1 AND  val <> 2
 

så hverken (1,1) heller ikke (2,2) fra kilden data1 overholde disse betingelser.



  1. MySQL fejl 1241:Operand skal indeholde 1 kolonne(r)

  2. Pivottabel og sammenkædning af kolonner

  3. Indtast disse tabelværdiparametre kraftigt

  4. Oprettelse af tabelnavne, der er reserverede ord/søgeord i MS SQL Server