MainframeSupports
tip uge 44/2016:

Nu tænker du nok, hvad kan der dog skrives om SQLCODE -803. Det betyder jo bare, at man forsøger at indsætte en række på en tabel, der findes i forvejen, og det bliver forhindret af et unikt index på tabellen. Så er den jo ikke længere. Sådan har jeg i hvert fald tænkt i rigtig mange år, men her for nylig blev jeg spurgt, om jeg kunne finde indholdet af den række, der blev forsøgt overskrevet.

For at kunne gøre dette, så skal man kende rækkens RID (Record IDentifier), og den bliver returneret i SQLCA arealet som den sidste værdi i feltet SQLERRMT. Uden RID'en kan opgaven ikke løses, så programmet, der får en -803 skal gemme SQLCA'et på en eller anden måde (udskrive det, evt. formateret). Værktøjer som CA Detector, IBM Query Monitor og BMC SQL Analyzer kan også opsamle SQLCA'et fra fejlende SQL statements, så her kan man også kigge efter RID'en. Ud over RID-værdien skal man selvfølgelig også vide, hvilken tabel rækken findes i. Denne oplysning står indirekte i SQLERRMT, for i dette felt står der også, hvilket index der er skyld i SQLCODE -803. En pænt formateret fejltekst kan for eksempel se således ud:

SQLCODE = -803, ERROR: AN INSERTED OR UPDATED VALUE IS INVALID
BECAUSE INDEX IN INDEX SPACE MYINDEX CONSTRAINS COLUMNS OF THE
TABLE SO NO TWO ROWS CAN CONTAIN DUPLICATE VALUES IN THOSE COLUMNS.
RID OF EXISTING ROW IS X'0000004208'.

Det er altså MYINDEX, der er skyld i miseren. Ved at slå op i DB2 kataloget finder jeg tabellen, og i dette eksempel antager jeg, at MYINDEX er et index på tabellen MYTABLE. Før dette tip ville jeg med meget besvær have fundet rækken med DSN1PRNT, men det kan gøres uendeligt meget lettere med SQL funktionen RID:

SELECT * FROM MYTABLE
WHERE RID(MYTABLE) = 16904

Og hvor kom så lige værdien 16904 fra? Jo, det er værdien X'0000004208' oversat til sin decimale værdi. Det kan du lettest gøre med en TSO SAY X2D(4208). Der er desværre ingen funktion eller udtryk i SQL, der kan lave oversættelsen. Og RID funktionen kræver, at værdien er en integer. Som argument til RID funktionen skal du angive den tabel, som din RID værdi tilhører.

For de af jer, der går op i performance, så skal I vide, at RID funktionen brugt på ovenstående måde får sin helt specielle accessvej, da DB2 kan lokalisere rækken med en eneste getpage. Og for de af jer, der ikke kender til opbygningen af en RID, så er de første fire bytes pagenummeret, og den sidste byte række-nummeret på pagen. Derfor kan der kun være 255 rækker på en page i DB2. Og dermed kan det samlede antal rækker i en DB2 tabel (indtil videre) højst være lidt over 1.000 mia. rækker.

Hver eneste række i en DB2 tabel har en unik RID værdi, men RID værdien kan skifte for samme række i forbindelse med en REORG, så lad være med at bruge RID-funktionen til at identificere rækker med. Men hvis du har en tabel, hvor to eller flere rækker er fuldstændig ens, så kan du bruge RID-funktionen til at fjerne de overflødige rækker med. Brug først RID funktionen i SELECT-listen og herefter som i eksemplet her.

Forrige danske tip        Last tip in english        Tip oversigten