MainframeSupports
tip uge 46/2006:

I alle de år jeg har arbejdet med DB2 har jeg prøvet at undgå NULL værdier. Samtidig er jeg ret vild med outer joins, som pr. definition introducerer NULL værdier. Heldigvis kan disse NULL værdier konverteres til noget fornuftigt med VALUE funktionen, som jeg tidligere har beskrevet. Problemer med forståelsen af NULL værdier oplever jeg er størst i WHERE betingelser. Det vil jeg forsøge at råde bod på i det følgende.

Antag at kolonne COLN i tabel TABLEX kan indeholde NULL værdier og rent faktisk også gør det for nogle af rækkerne i TABLEX. Her er så et eksempel på et SQL kald mod TABLEX:

select COL1, COL2, COL3
from TABLEX
where COLN <> ''

Her er det rigtig gode spørgsmål så om rækker, hvor COLN er NULL bliver returneret. Det rigtige svar er, at det bliver de ikke. NULL er simpelthen ikke lig, større end, mindre end eller forskellig fra nogen almindelig værdi. Med andre ord: hvis du i dine WHERE betingelser refererer til en kolonne, der indeholder NULL værdier, så vil de tilsvarende rækker blive sorteret fra.

Den eneste måde at få rækker med NULL værdier i COLN returneret er ved at ændre ovenstående betingelse til COLN <> '' OR COLN IS NULL. Netop på grund af NULL værdiens helt specielle status har SQL indbygget de to udtryk COLN IS NULL eller COLN IS NOT NULL. Du kan ikke skrive COLN = NULL eller COLN <> NULL, det er simpelthen ulovlig syntaks.

Med hensyn til outer joins har jeg i den forløbne uge endnu en gang konstateret, at kendskabet til dem er forsvindende lille og nu har jeg også en teori om hvorfor. Det skyldes i mine øjne netop måden NULL værdier virker på. Et eksempel:

select A.COL1, B.COL2
from TABLEA A left outer join TABLEB B
  on A.JOINCOL = B.JOINCOL
where A.COL1 > 100
  and B.COLX = 'X'

Dette SQL-kald er et glimrende eksempel på, hvordan mange af os får det første indtryk af outer join faciliteten. Vi starter med det samme SQL-kald uden den sidste AND. Vi konstaterer, at det virker præcis som det skal, og vi kan ikke få hænderne ned i bare begejstring. Så vil vi gerne lige have en betingelse på den tabel, vi outer joiner med, eksemplificeret med AND b.COLX = 'X', og så knækker filmen for os. Så virker SQL-kaldet lige pludselig bare som en almindelig inner join og hænderne kommer meget hurtigt ned igen. De fleste af os opgiver og dropper outer joins på stedet, for der må jo være noget galt med DB2. Men det er der ikke. Miseren skyldes udelukkende, at hvis en række i TABLEA ikke matcher en række i TABLEB, så får alle kolonnerne i TABLEB for den pågældende række tildelt værdien NULL. B.COLX er altså NULL for disse rækker og B.COLX = 'X' matcher ikke NULL, ligesom enhver anden betingelse bortset fra IS NULL heller ikke matcher.

Redningen i ovenstående eksempel kan være enten at flytte AND B.COLX = 'X' op som en del af ON kriteriet, for det er faktisk muligt og fuldt lovligt, eller også at ændre AND B.COLX = 'X' til AND (B.COLX = 'X' OR B.COLX IS NULL). Du skal bare være opmærksom på, at disse to muligheder producerer to forskellige resultater afhængig af data. Prøv dig frem for at finde ud af, hvad der virker mest rigtigt i din konkrete problemstilling.

Forrige danske tip        Last tip in english        Tip oversigten