MainframeSupports
tip uge 14/2006:

Nu om dage er det meget moderne at benytte et timestamp som entydig nøgle. Et af problemerne i den forbindelse er, at man risikerer, at to inserts mod den samme tabel sker med samme timestamp. En anden irriterende detalje er, at man ikke kan lave INSERT INTO ... SELECT * FROM ... på sådanne tabeller, hvis man vil generere nye entydige timestamps med CURRENT TIMESTAMP. Hvis din installation kører version 7 eller mere på DB2, så er der hjælp forude med funktionen GENERATE_UNIQUE.

Først og fremmest skal du sikre dig, at GENERATE_UNIQUE virker på din DB2. Det kan du let gøre med en:

SELECT TIMESTAMP(GENERATE_UNIQUE())
FROM SYSIBM.SYSDATABASE
FETCH FIRST 10 ROWS ONLY

Du skal huske () efter GENERATE_UNIQUE, ellers tror DB2, at det er en kolonne. Hvis ovenstående statement fejler med andet end en -904, så er GENERATE_UNIQUE ikke installeret på din DB2. Hvis du kører DB2 version 7 kan du bede din DB2 systemprogrammør om at installere APAR PQ70901, hvorefter funktionen gerne skulle virke. Hvis du får en -904, så er funktionen ikke installeret korrekt, eller jeres hardware/software er ikke opgraderet tilstrækkeligt til at GENERATE_UNIQUE virker.

Hvis ovenstående SQL kald virker og udskriver 10 timestamps, så læg mærke til, at de ikke er ens og, at de er i stigende orden. Kombinationen af GENERATE_UNIQUE og TIMESTAMP funktionen leverer altså et entydigt timestamp pr. returneret række. Hvis du laver en INSERT INTO ... SELECT * FROM ... vil TIMESTAMP(GENERATE_UNIQUE()) virke på samme måde, og du kan altså give de enkelte rækker returneret af SELECT delen entydige timestamps.

To INSERT statements eksekveret samtidigt mod samme DB2 kan stadig resultere i, at det ene bliver afvist med en -803. Det problem kan også løses med GENERATE_UNIQUE ved at definere en ny entydig nøgle-kolonne (f.eks. kaldet key_column) som en CHAR(13) FOR BIT DATA. Kolonner med denne definition kan sættes direkte til værdien returneret af GENERATE_UNIQUE og vil altid være entydig, selv i et data sharing miljø. Denne metode kan selvfølgelig kun anvendes på nye tabeller. Det gode ved metoden er, at man kan udføre en TIMESTAMP(key_column) og dermed få at vide, hvornår kolonnen blev oprettet. Man kan altså få samme information som med en TIMESTAMP nøgle-kolonne, men bare med fuld entydighed.

Til sidst skal jeg huske at nævne, at DB2 version 8 i såkaldt New Function Mode (NFM) giver lidt sjove resultater for TIMESTAMP(GENERATE_UNIQUE()), hvis en af tabellerne i FROM delen er en UNICODE tabel. Så bliver resultatet et timestamp i unicode, og det er ikke til at læse. Dette problem løses ved at lave en CHAR(TIMESTAMP(GENERATE_UNIQUE())). En anden detalje er, at i resultatet for en SELECT dannes GENERATE_UNIQUE værdierne før en eventuel SORT. Prøv eksempelvis to nedenstående SQL-kald for at se konsekvenserne af dette:

SELECT TIMESTAMP(GENERATE_UNIQUE())
FROM SYSIBM.SYSDATABASE
ORDER BY DBID
FETCH FIRST 10 ROWS ONLY
;
SELECT TIMESTAMP(GENERATE_UNIQUE())
FROM SYSIBM.SYSDATABASE
ORDER BY NAME
FETCH FIRST 10 ROWS ONLY
;

I det første SQL-kald vil de 10 timestamps ikke være i stigende orden, da dette SQL-kald udløser en intern DB2 sort (med mindre der er defineret et index på DBID i jeres installation). I det sidste SQL-kald er de 10 timestamps i stigende orden, da DB2 henter rækkerne i rækkefølgen angivet af et index og dermed undgår den interne sortering.

Forrige danske tip        Last tip in english        Tip oversigten