MainframeSupports
tip uge 7/2014:

Fornylig fik jeg en pudsig opgave, hvor jeg vha. statisk SQL i et program skulle vælge mellem at hente alle rækker, der matchede en bestemt værdi i en kolonne, eller hente alle de rækker, der ikke matchede samme værdi i kolonnen. En ofte set løsning på lignende problemstilinger er at lave to cursore, en for hvert af de to valgmuligheder. Det giver en frygtelig masse næsten ens kode i programmet og en masse styring af, hvilken cursor, der er den aktive.

Det vil selvfølgelig være nemmere med en cursor, der håndterer begge valg, og der findes faktisk en generel løsning på denne problemstilling i statisk SQL næsten uanset, hvor mange muligheder, der skal vælges imellem. Her er et simpelt eksempel:

SELECT COLUMNB, COLUMNC
FROM MYTABLE
WHERE (COLUMNA = :VALUEA OR 1 = :DISABLE1)
  AND (COLUMNA <> :VALUEA OR 1 = :DISABLE2)

Hostvariablen :VALUEA sættes til den ønskede værdi, og :DISABLE1 sættes til 1, hvis "lig med" skal ignoreres, mens :DISABLE2 sættes til 0 (eller en anden værdi forskellig fra 1) for at få udført en "forskellig fra". Her kan du med andre ord selv styre, hvilke betingelser i WHERE-delen, der skal sortere rækker fra. Ovenstående metode har desværre den meget store ulempe, at den ikke kan udnytte nogen af de index, hvor COLUMNA måtte indgå. Dette gælder selvfølgelig kun for de kolonner, hvor der er knyttet en OR 1 = :DISABLE til betingelsen. I eksemplet vil MYTABLE blive gennemsøgt med en tablespacescan hver gang uanset tilhørende index-definitioner og indholdet af de forskellige hostvariable.

I det konkrete eksempel kan problemet med tablespacescan løses, hvis der er et index på COLUMNA, på følgende måde:

SELECT COLUMNB, COLUMNC
FROM MYTABLE
WHERE COLUMNA BETWEEN :LOWVALUE AND :HIGHVALUE
  AND COLUMNA <> :VALUEA

Hvis der skal udføres en "lig med", så sættes :LOWVALUE og :HIGHVALUE til samme værdi, nemlig den værdi, der skal returneres rækker for, mens :VALUEA sættes til en værdi forskellig fra den ønskede værdi. Hvis der derimod skal udføres en "forskellig fra", så skal :LOWVALUE sættes til den lavest mulige værdi for COLUMNA og :HIGHVALUE til den højest mulige værdi. :VALUEA sættes til den værdi, der ikke skal returneres rækker for.

De to viste SQL statements med tilhørende tildeling af værdier til de benyttede hostvariable tilbyder samme funktionalitet. Det sidste eksempel kan udnytte et eventuelt index og er derfor at foretrække. Det første eksempel giver dog den største fleksibilitet og mest generelle anvendelse, og kan især anvendes til mindre tabeller (her i 2014 er en tabel med under en million rækker at regne for en mindre tabel), hvis ellers statementet ikke udføres flere tusind gange dagligt.

Forrige danske tip        Last tip in english        Tip oversigten