28.11.2014 Views

Sadrzaj - Alas

Sadrzaj - Alas

Sadrzaj - Alas

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Sadržaj<br />

I Ugnježdeni SQL 1<br />

1 Uvod 3<br />

2 Osnove kodiranja SQL-a u aplikativnom programu 5<br />

2.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />

2.2 Deklarativne SQL naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6<br />

2.3 Host promenljive i strukture . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />

2.4 Indikatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />

2.4.1 Osnovno o indikatorima . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />

2.4.2 Postavljanje NULL vrednosti . . . . . . . . . . . . . . . . . . . . . . 10<br />

2.4.3 Promena kodirajućeg skupa karaktera za host promenljivu . . . . . . 10<br />

3 Obrada grešaka pri SQL upitima 11<br />

3.1 SQLCODE i SQLSTATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />

3.2 Konverzija koda greške u tekstualno objašnjenje . . . . . . . . . . . . . . . 12<br />

3.3 WHENEVER naredba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />

3.4 Otkrivanje grešaka pri aritmetičkim operacijama i konverziji . . . . . . . . . 13<br />

4 Kursori 15<br />

4.1 Rad sa kursorima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

4.1.1 Otvaranje kursora . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

4.1.2 Čitanje podataka kursorom . . . . . . . . . . . . . . . . . . . . . . . 16<br />

4.1.3 Ažuriranje podataka kursorom . . . . . . . . . . . . . . . . . . . . . 18<br />

4.1.4 Brisanje podataka kursorom . . . . . . . . . . . . . . . . . . . . . . . 18<br />

4.1.5 Zatvaranje kursora . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

4.1.6 Tipovi kursora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

5 Pravila za kodiranje SQL naredbi u PL/I aplikacijama 23<br />

5.1 Uključivanje SQLCODE i SQLSTATE . . . . . . . . . . . . . . . . . . . . . 23<br />

5.2 Pravila kodiranja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />

5.3 Upotreba host promenljivih . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

5.3.1 Deklaracija host promenljivih . . . . . . . . . . . . . . . . . . . . . . 25<br />

5.3.2 Konverzija SQL kodova u tekstualni zapis . . . . . . . . . . . . . . . 25<br />

6 Pravila za kodiranje SQL naredbi u C aplikacijama 27<br />

6.1 Osnovna pravila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />

6.2 Strukture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />

6.3 Osnovni zahtevi za host promenljive u C-u . . . . . . . . . . . . . . . . . . . 29


ii<br />

SADRŽAJ<br />

6.4 Karakter host promenljive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />

II Transakcije, restart i oporavak u programu 31<br />

7 Uvod 33<br />

8 Transakcije 35<br />

8.1 Jedinica oporavka i otvoreni kursori . . . . . . . . . . . . . . . . . . . . . . 36<br />

8.2 Opšti algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />

8.3 Tačke čuvanja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />

III Dodatne programske tehnike 43<br />

9 Dinamički SQL 45<br />

9.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

9.2 Izbor izmedju dinamičkog i statičkog SQL-a . . . . . . . . . . . . . . . . . . 45<br />

9.2.1 Šta može da uradi program koji koristi dinamički SQL . . . . . . . . 46<br />

9.2.2 Performanse statičkog i dinamičkog SQL-a . . . . . . . . . . . . . . . 46<br />

9.3 Keširanje naredbi sa dinamičkim SQL-om . . . . . . . . . . . . . . . . . . . 47<br />

9.4 Čuvanje pripremljene naredbe posle COMMIT-a . . . . . . . . . . . . . . . 47<br />

9.5 Izbor host jezika za aplikacije sa dinamičkim SQL-om . . . . . . . . . . . . 48<br />

9.6 Dinamički SQL sa ne-SELECT naredbom . . . . . . . . . . . . . . . . . . . 48<br />

9.6.1 Izvršavanje upotrebom EXECUTE IMMEDIATE . . . . . . . . . . . 48<br />

9.6.2 Izvršavanje upotrebom PREPARE i EXECUTE . . . . . . . . . . . 48<br />

9.7 Dinamički SQL sa fiksnom listom u SELECT naredbi . . . . . . . . . . . . 50<br />

9.8 Dinamički SQL sa promenljivom listom u SELECT naredbi . . . . . . . . . 51<br />

10 Podešavanje upita 53<br />

10.1 Opšta pravila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />

10.2 Pisanje efikasnijih predikata . . . . . . . . . . . . . . . . . . . . . . . . . . . 54<br />

10.3 Efikasna upotreba podupita . . . . . . . . . . . . . . . . . . . . . . . . . . . 54<br />

10.3.1 Korelirani podupiti . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />

10.3.2 Nekorelirani podupiti . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />

10.3.3 Transformacija podupita u spajanje . . . . . . . . . . . . . . . . . . 56<br />

10.4 Specijalne tehnike koje utiču na pristupni put . . . . . . . . . . . . . . . . . 56<br />

10.4.1 Dobijanje informacija o pristupnim putevima . . . . . . . . . . . . . 56<br />

10.4.2 Upotreba OPTIMIZE FOR n ROWS . . . . . . . . . . . . . . . . . . 56<br />

10.4.3 Smanjenje broja uparenih kolona . . . . . . . . . . . . . . . . . . . . 57<br />

10.4.4 Promena unutrašnjeg u spoljašnje spajanje . . . . . . . . . . . . . . 58<br />

10.4.5 Ažuriranje statistike u katalogu . . . . . . . . . . . . . . . . . . . . . 58<br />

10.5 Osnovno o uskladištenim (stored) procedurama . . . . . . . . . . . . . . . . 59<br />

10.6 Osnovno o radu sa distribuiranim podacima . . . . . . . . . . . . . . . . . . 60<br />

10.6.1 Vezivanje programa koji rade sa DRDA pristupom . . . . . . . . . . 62<br />

10.7 EXPLAIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />

10.7.1 Neke informacije o EXPLAIN-u . . . . . . . . . . . . . . . . . . . . . 63<br />

10.8 Pristupni putevi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64<br />

10.8.1 Tehnike za poboljšavanje pristupnog puta . . . . . . . . . . . . . . . 64


SADRŽAJ<br />

iii<br />

10.8.2 Pristupni putevi za jednu tabelu . . . . . . . . . . . . . . . . . . . . 65<br />

10.8.3 Pristupni putevi za više tabela . . . . . . . . . . . . . . . . . . . . . 67<br />

11 Literatura 71<br />

11.1 DB2 za OS/390 V7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71<br />

11.2 QMF V7R2 for OS/390 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72<br />

11.3 Dodatna literatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72<br />

A Značenja polja u SQLCA 73<br />

B Izgled SQLCA strukture 79<br />

C Klase SQLSTATE kodova 81


Deo I<br />

Ugnježdeni SQL


Glava 1<br />

Uvod<br />

Pored interkativnog SQL-a, do podataka u DB2 može da se pristupi i korišćenjem aplikativnih<br />

programa. Radi izvršavanja SQL naredbi program mora da komunicira sa DB2. Ta<br />

komunikacija sa DB2 V7.1 za OS/390 i z/OS se može izvesti na različite načine:<br />

• Pomoću statičkog SQL-a<br />

• Pomoću ugneždenog dinamičkog SQL-a<br />

• Pomoću ODBC (eng. Open DataBase Connectivity protokola<br />

• Pomoću podrške za JDBC (eng. Java DataBase Connectivity<br />

U daljem tekstu će biti razmatrani statički i dinamički SQL. ODBC dopušta pristup preko<br />

poziva ODBC funkcija u programu. SQL naredbe se izvršava ju prenošenjem ka DB2<br />

preko poziva ODBC funkcija. ODBC eliminiše potrebu za prekompilacijem i vezivanjem<br />

aplikacija i povećava portabilnost aplikacija korišćenjem ODBC interfejsa.<br />

U slučaju da se koristi Java potrebno je koristiti JDBC. JDBC je sličan ODBC-u ali je<br />

dizajniran za korišćenje sa Java programima i stoga je bolji izbor od ODBC-a za korišćenje<br />

u Java aplikacijama.<br />

Za detaljnije informacije o krišćenju ODBC i JDBC videti DB2 V7.1 ODBC Guide and<br />

Reference, SC26-9941-02


Glava 2<br />

Osnove kodiranja SQL-a u<br />

aplikativnom programu<br />

2.1 Uvod<br />

U prethodnom kursu je rečeno da se SQL u DB2 koristi i kao upitni jezik prilikom interaktivnog<br />

postavljanja upita (SPUFI, QMF) i kao programski jezik za rad sa bazom podataka.<br />

Termin ”Ugnježdeni SQL” označava SQL naredbe koje se nalaze uključene u programu<br />

napisanom na nekom od viših programskih jezika ili asembleru. Takav programski jezik<br />

se naziva ”host jezik”. DB2 podržava PL/I, C, C++, FORTAN, COBOL, APL2, BASIC,<br />

Ada, Prolog/MVS & VM, REXX i assembler kao host jezike, odnosno jezike u kojima se<br />

mogu pisati programi koji uključuju SQL naredbe.<br />

SQL ugnježden u višem programskom jeziku nije novi jezik; štaviše, svaka SQL naredba<br />

koja može da se koristi interaktivno, može da bude uključena u program kao ugnježdena<br />

SQL naredba. Pri tome je potrebno eventualno samo dopuniti pojedine detalje koji se<br />

odnose na specifičnosti konkretnog programskog jezika.<br />

Pravila koja mora da zadovoljava ugnježdeni SQL su:<br />

1. Ugnježdena SQL naredba obavezno poseduje prefiks EXEC SQL i završava se specijalnim<br />

terminator simbolom (u PL/I ’;’)<br />

2. SQL naredba se obavezno piše velikim slovima (sem literala i host promenljivih<br />

(videti kasnije) koji se pišu onakvi kakvi su deklarisani). 1<br />

3. Postoje dve vrste ugnježdenih SQL naredbi: izvršne i deklarativne. Izvršne naredbe<br />

mogu da se nalaze na onim mestima gde mogu da se nalaze i izvršne naredbe odgovarajućeg<br />

host jezika. Primer izvršne SQL naredbe predstavlja bilo koja od SQL<br />

naredbi koja može da se izvrši interaktivno (naravno, uz dodavanje prefiksa EXEC<br />

SQL). Za razliku od njih, deklarativne naredbe (videti u daljem tekstu) mogu da<br />

se nalaze na mestima gde se u programima javljaju deklaracije. Deklarativne SQL<br />

naredbe obradjuje DB2 prekompilator.<br />

1 Za PL/I ovo pravilo ne važi, jer PL/I prevodilac ne pravi razliku izmedju malih i velikih slova.


6 Osnove kodiranja SQL-a u aplikativnom programu<br />

2.2 Deklarativne SQL naredbe<br />

Pre korišćenja SQL naredbi kojima se dobijaju, ažuriraju, brišu ili unose podaci poželjno<br />

je opisati tabele i poglede kojima se pristupa u takvim naredbama. Opisivanje se vrši<br />

uključivanjem EXEC SQL DECLARE naredbe u program.<br />

Deklaracija tabela i pogleda nije obavezna; nepostojanje deklaracija ne utiče na ispravnost<br />

programa. U slučaju da u programu deklaracije ne postoje, prekompilator će generisati<br />

upozorenje o nepostojanju deklaracija. Medjutim, deklarisanje tabela i pogleda poseduje<br />

odredjene prednosti:<br />

• bolja dokumentovanost programa: u DECLARE naredbi se navodi struktura tabele<br />

ili pogleda sa kojim se radi, kao i tip podataka svakog atributa tabele. Time je<br />

olakšan posao programeru koji tu poseduje pregled imena kolona i tipova podataka<br />

u tabeli.<br />

• navodjenjem deklaracija olakšava se posao DB2 prekompilatoru koji deklaracije koristi<br />

prilikom provere korektnosti naziva kolona i tipova podataka u SQL naredbama.<br />

Deklaracija tabele (ili pogleda, bez razlike) se vrši navodjenjem naredbe<br />

EXEC SQL DECLARE ime-tabele TABLE .... Na primer,<br />

EXEC SQL DECLARE SNABDEVACI TABLE<br />

(SNABDEVACI<br />

SIME<br />

STATUS<br />

GRAD<br />

CHAR(5) NOT NULL,<br />

CHAR(20),<br />

SMALLINT,<br />

CHAR(15));<br />

Programer može sam da unosi deklaraciju tabela (i/ili pogleda) ili može da koristi sistemski<br />

generator deklaracija DCLGEN. DCLGEN je generator deklaracija koji formira<br />

DECLARE naredbe za tabele i host strukture koje se mogu koristiti u C, COBOL ili<br />

PL/I programima. DCLGEN se može koristiti pre prekompilacije programa. Deklaracije<br />

formirane sa DCLGEN-om se uključuju u program bilo navodjenjem EXEC SQL INCLUDE<br />

ime člana biblioteke; bilo uključivanjem (npr. editorom) člana biblioteke koji sadrži generisane<br />

deklaracije u izvorni oblik programa.<br />

DCLGEN se može pozvati na različite načine:<br />

• Preko ISPF-a kroz DB2I, izborom DCLGEN opcije na DB2I primarnom panelu.<br />

• Direktno iz TSO-a pozivnom TSO komande DSN i unošnejem podkomande<br />

DCLGEN.<br />

• Iz CLIST procedura (bilo interkativno ili u batch-u) pozivanjem DSN i DCLGEN, i<br />

• Iz JCL-a navodjenjem potrebnih parametara.<br />

Ako se u programu upotrebljavaju tzv. kursori tada deklarativna naredba za kursor<br />

MORA da postoji. O radu sa kursorima i ostalim deklarativnim naredbama (kao WHENEVER)<br />

biće reči kasnije.


Host promenljive i strukture 7<br />

2.3 Host promenljive i strukture<br />

Ugnježdene SQL naredbe mogu da uključe reference na promenljive i strukture višeg programskog<br />

jezika. Takve promenljive (strukture) se nazivaju host promenljive (strukture). 2<br />

Host promenljive mogu da sadrže samo pojedinačne vrednosti, ali ne i celu tabelu, kao<br />

ni sve vrednosti u jednoj koloni. Host promenljive moraju da se deklarišu pre korišćenja<br />

u SQL naredbama. Deklaracija se navodi prema pravilima host jezika, i, u zavisnosti od<br />

opcija prekompilatora, može ali ne mora da se navede u bloku naredbi ograničenom sa<br />

EXEC SQL BEGIN DECLARE SECTION<br />

... deklaracije host promenljivih i indikatora<br />

EXEC SQL END DECLARE SECTION<br />

Pri tome tip host promenljive mora da odgovara tipu podatka koji se javlja u SQL upitu<br />

na onoj poziciji gde se host promenljiva pojavljuje. Ispred host promenljive koja se pojavljuje<br />

u SQL naredbama mora da se navede dvotačka kao prefiks. Dvotačka ne sme da<br />

se pojavi kao prefiks kod host promenljivih koje se koriste van SQL upita.<br />

Host promenljive predstavljaju mesto kod koga se interaktivni SQL razlikuje od ugnježdenih<br />

SQL naredbi. Kod rada sa interaktivnim SQL-om rezultati upita kod kojih se traži dohvatanje<br />

podataka iz baze se prikazuju na ekranu terminala, štampaču ili u unapred<br />

odredjenoj datoteci. Kod aplikativnog programa to nije slučaj; SQL naredba se izvrši,<br />

dohvati tražene podatke i preda kontrolu aplikativnom programu. Jasno je da u ovom<br />

slučaju treba eksplicitno obezbediti prostor u memoriji u koji treba smestiti podatke jer<br />

podaci ne mogu da budu ”tu negde”, odnosno da ”ostanu da vise u vazduhu”. Upravo<br />

se host promenljive koriste kao prostor u kome se smeštaju dobijeni podaci. Koje će<br />

host promenljive biti korišćene za smeštanje podataka odredjuje se navodjenjem INTO<br />

klauzule kod SELECT ili FETCH SQL naredbe. Mogu se navesti prijemno polje (tj.<br />

host struktura) ili lista host promenljivih. Ako je programer siguran da je rezultat upita<br />

NAJVIŠE JEDAN RED tada se SQL naredbe mogu kodirati u programu na isti način kao<br />

i u interaktivnom SQL-u, uz dodavanje INTO naredbe. Takodje se mogu koristiti SQL<br />

skalarne i agregatne funkcije sve dok je ispunjen uslov da je rezultat upita najviše jedan<br />

red (bez obzira na broj kolona ili izračunatih vrednosti).<br />

Napomena 1<br />

Ako SELECT naredba kao rezultat upita daje više od jednog reda tada se javlja greška i<br />

podaci koji se dobiju su ili nedefinisani ili nepredvidivi.<br />

Tipična mesta gde se koriste host promenljive su:<br />

• kao prijemno polje pri čitanju podataka (u INTO ili FETCH klauzuli), npr.<br />

EXEC SQL<br />

SELECT SIME INTO :ime FROM SNABDEVACI WHERE SRBR=’S1’;<br />

EXEC SQL<br />

SELECT SIME, STATUS, GRAD INTO :ime, :status, :grad<br />

FROM SNABDEVACI<br />

WHERE SRBR=’S1’;<br />

2 Nadalje se podrazumeva da sva pravila koja važe za promenljive važe i za strukture.


8 Osnove kodiranja SQL-a u aplikativnom programu<br />

EXEC SQL<br />

SELECT SIME, STATUS, GRAD INTO :polje<br />

FROM SNABDEVACI<br />

WHERE SRBR=’S1’;<br />

gde je polje deklarisano kao<br />

dcl 1 polje,<br />

2 ime char(20),<br />

2 status bin fixed(15),<br />

2 grad char(15);<br />

• u WHERE klauzuli, za navodjenje vrednosti u predikatu kojim se vrši restrikcija<br />

uslova pretraživanja ili na mestu gde može da zameni literal. Npr.<br />

EXEC SQL<br />

SELECT SIME INTO :ime FROM SNABDEVACI WHERE SRBR=:rednibroj;<br />

• kao vrednost u SELECT naredbi. Npr.<br />

EXEC SQL<br />

SELECT SIME, :broj, STATUS+:broj INTO :ime, :zalihe, :status,<br />

FROM SNABDEVACI<br />

WHERE SRBR=:rbr;<br />

• kao vrednost u ostalim klauzulama u SQL naredbi:<br />

– SET klauzuli u UPDATE naredbi<br />

– VALUES klauzuli u INSERT naredbi<br />

– HAVING klauzuli<br />

– ...<br />

Ilustracija upotrebe host promenljivih data je u programima primer1 i primer2 koji su<br />

navedeni u dodatku ??. 3<br />

2.4 Indikatori<br />

2.4.1 Osnovno o indikatorima<br />

Kako u aplikativnom programu otkriti da li je rezulat nekog upita NULL? Nije moguće<br />

postaviti pitanje da li je sadržaj neke host promenljive jednak NULL, već se pri rešavanju<br />

ovog problema koriste indikatori.<br />

Indikator promenljiva je ceo broj od jedne polureči (dva bajta) koji se može koristiti za:<br />

3 Izvorni kodovi programa se nalaze u datoteci HDB2000.T.PLI. Primeri programa dati od strane IBM-a<br />

se nalaze u datoteci DSN710.SDSNSAMP.


Indikatori 9<br />

• odredjivanje da li se host promenljiva koristi kao prijemno polje za kolonu koja<br />

može da poseduje NULL vrednosti. Ako je vrednost u koloni koja se traži NULL,<br />

DB2 upisuje negativnu vrednost u indikator promenljivu i ne menja vrednost host<br />

promenljive. Ako je NULL zbog greške pri numeričkoj konverziji ili pri izračunavanju<br />

aritmetičkog izraza, DB2 postavlja indikator promenljivu na -2.<br />

Ako se ne koristi indikator promenljiva, a pojavi se NULL vrednost u nekoj koloni<br />

rezultata, tada se u programu dobija kod koji označava grešku pri izvršavanju SQL<br />

naredbe.<br />

• proveru da li je došlo do skraćivanja karakter niske koja se dobija kao vrednost upita.<br />

Ako indikator promenljiva sadrži pozitivnu vrednost tada ta vrednost predstavlja<br />

pravu dužinu niske. Više o dijagnosticiranju ovakvih tipova grešaka videti u odeljku<br />

3.<br />

• unošenje NULL vrednosti u tabele (bilo preko INSERT ili UPDATE naredbe).<br />

• Odredjivanje da li se vrednost karaktera može konvertovati pri dodeljivanju vrednosti<br />

host promenljivoj.<br />

• Odredjivanje drugog dela vremenske vrednosti koja je odsečena pri dodeljivanju<br />

vrednosti host promenljivoj.<br />

Indikator promenljiva se može kodirati u programu na dva načina:<br />

1. navodjenjem imena indikator promenljive (kome prethodi dvotačka) neposredno iza<br />

imena host promenljive, i<br />

2. korišćenjem ključne reči INDICATOR izmedju host i indikator promenljive. Pri<br />

tome reč INDICATOR nije rezervisana reč SQL-a.<br />

Sledeća dva primera su ekvivalentna:<br />

EXEC SQL SELECT GRAD INTO :dgrad:indik<br />

FROM DELOVI<br />

WHERE DRBR=’D6’;<br />

EXEC SQL SELECT GRAD INTO :dgrad INDICATOR :indik<br />

FROM DELOVI<br />

WHERE DRBR=’D6’;<br />

Tehnika rada sa indikatorima se ne menja kada se podaci dobijaju korišćenjem kursora.<br />

Za host strukture koje se koriste u programima definišu se odgovarajuće indikator strukture<br />

(kao niz BIN FIXED(15) elemenata). Broj elemenata u strukturi u u nizu moraju biti<br />

isti. U SQL naredbama se kodira tako što se navede ime strukture za kojim sledi ime<br />

indikator strukture. Ako vrednost bilo kot od atributa može biti NULL tada se mora<br />

koristiti indikator struktura koja sadrži test za sve kolone (naravno, ukoliko se koristi host<br />

struktura a ne više host promenljivih). Primer upotrebe indikator promenljivih je prikazan<br />

u programu primer3.


10 Osnove kodiranja SQL-a u aplikativnom programu<br />

2.4.2 Postavljanje NULL vrednosti<br />

Indikator promenljive se mogu koristiti i za postavljanje NULL vrednosti u tabelama.<br />

Kada se izvršava UPDATE ili INSERT naredba DB2 proverava sadržaj indikator<br />

promenljive (ako postoji). Ako je sadržaj negativna vrednost, vrednosti u koloni odgovarajuće<br />

tabele biće postavljene na NULL. Ako je vrednost indikator promenljive veća<br />

od -1 tada vrednost odgovarajuće host promenljive sadrži vrednost koju treba postaviti u<br />

kolonu.<br />

Primer upotrebe indikator promenljivih za postavljanje NULL vrednosti u tabelama je<br />

prikazan u programu primer4.<br />

Za host strukture koje se koriste u programima definišu se odgovarajuće indikator strukture<br />

(kao niz promenljivih tipa BIN FIXED(15)). Broj elemenata u strukturi u i nizu moraju<br />

biti isti. U SQL naredbama ovakav slučaj se kodira tako što se navede ime strukture za<br />

kojim sledi ime indikator strukture. Primer upotrebe indikator strukure (tj. niza indikator<br />

promenljivih) je prikazan u programu primer3.<br />

Ako bilo koja od rezultujućih kolona nekog upita može biti NULL, i ukoliko se koristi<br />

host struktura a ne više host promenljivih, tada se mora koristiti indikator struktura koja<br />

sadrži proveru za NULL vrednosti u svim kolonama (bez obzira što možda neka od kolona<br />

nikada na može da sadrži NULL vrednost).<br />

Napomena 2<br />

Indikator promenljiva koja se koristi u WHERE naredbi ne sme da sadrži negativne vrednosti.<br />

Za ispitivanje da li je nešto NULL koristi se isključivo IS NULL ili IS NOT NULL.<br />

Za formiranje opisa tabela i konstrukciju host struktura koje odgovaraju tabeli može se<br />

koristiti sistemski program DCLGEN.<br />

2.4.3 Promena kodirajućeg skupa karaktera za host promenljivu<br />

Sve DB2 niske različite od BLOB poseduju šemu enkodiranja i skup kodirajućih karaktera<br />

(CCSID). NZa dodljivanje šeme enkodiranja i CCSID pojedinačnim host promenljivim se<br />

može koristiti DECLARE VARIABLE naredba.<br />

Na primer, sa<br />

EXEC SQL DECLARE --prom-- VARIABLE CCSID 1208;<br />

se deklariše karakter host promneljiva u Unicode CCSID 1208.


Glava 3<br />

Obrada grešaka pri SQL upitima<br />

Da bi program koji uključuje SQL naredbe komunicirao sa DB2 potrebno je da poseduje<br />

prostor preko koga se obavlja ta komunikacija. To polje se naziva SQL polje za komunikaciju<br />

(SQL communication area, SQLCA).<br />

Kada DB2 izvršava SQL naredbe iz aplikativnog programa, povratni kod se upisuje u<br />

polja SQLCODE i SQLSTATE u SQLCA. Na osnovu upisanog koda se odredjuje da li je<br />

naredba uspešno izvršena ili ne.<br />

SQLCA je struktura promenljivih koja se ažurira posle izvršavanja svake SQL naredbe.<br />

Promenljive iz SQLCA se koriste kao alat pri dijagnosticiranju pojave eventualne greške.<br />

Izgled SQLCA strukture i značenje promenljivih u SQLCA su prikazani u dodatku A.<br />

Aplikativni program koji sadrži izvršne SQL naredbe (tj. bilo koje sem DECLARE, IN-<br />

CLUDE, WHENEVER) obavezno mora da poseduje tačno jednu SQLCA. Izuzetak od<br />

ovog pravila za PL/I programe je slučaj kada se program prekompilira sa opcijom STD-<br />

SQL(YES) (videti deo o opcijama prekompilatora). U host jezicima SQL INCLUDE<br />

naredba se može iskoristiti za deklarisanje SQLCA tako što se pre bilo koje SQL naredbe,<br />

a najbolje na početku programa, navede:<br />

EXEC SQL INCLUDE SQLCA;<br />

Izgled strukture uključene ovom naredbom prikazan je u dodatku B.<br />

3.1 SQLCODE i SQLSTATE<br />

Korisnik koji radi sa relacionim sistemom mora da dobije informaciju o uspešnosti<br />

izvršavanja njegovog zahteva. Željenu informaciju, u obliku povratnog koda, relacioni<br />

sistem DB2 upisuje u polje nazvano SQLCODE. SQLCODE je celbrojna promenljiva.<br />

DB2 vraća sledeće vrednosti SQLCODE-a:<br />

• Ako je prilikom izvršavanja upita došlo do greške SQLCODE dobija negativnu vrednost;<br />

• svi izuzeti (ali važeći) uslovi postavljaju pozitivnu vrednost; (npr. SQLCODE=100<br />

predstavlja informaciju da nema podataka koji zadovoljavaju uslov upita)<br />

• u slučaju da nema grešaka ili izuzetih uslova SQLCODE se postavlja na nulu.<br />

Značenja SQLCODE-a koja su različita od 0 i 100 variraju u zavisnosti od različitih implementacija<br />

SQL-a i RSUBP-a.


12 Obrada grešaka pri SQL upitima<br />

SQL:1992 standard je definisao SQLSTATE kao promenljivu koja sadrži povratnu informaciju<br />

o izvršavanju zahteva u bazi podataka. Funkcija SQLSTATE je slična funkciji<br />

SQLCODE-a, sa tom razlikom što je SQLSTATE karakter promenljiva. Kodovi kod ovih<br />

dveju promenljivih su različiti - tako npr. kod ’02000’ kod SQLSTATE-a ima isto značenje<br />

kao i kod +100 kod SQLCODE-a. DB2 podržava i SQLCODE i SQLSTATE.<br />

SQLSTATE kod poseduje odredjenu strukturu. Prva dva karaktera predstavlaju kod SQL-<br />

STATE klase. Kod ’00’ označava uspešno izvršenje. Kod ’01’ označava kodove vezane za<br />

upozorenje, a ’02’ uslov da nema više slogova (npr. SQLSTATE ’02000’ predstavlja informaciju<br />

da nema podataka koji zadovoljavaju uslov upita). Sve ostale klase kodova<br />

označavaju greške. Značenja SQLSTATE kodova po grupama su prikazana u dodatku C.<br />

Vrednosti promenljivih SQLCODE i SQLSTATE se postavljaju posle izvršavanja svakog<br />

SQL upita. Prednosti upotrebe SQLCODE-a u odnosu na SQLSTATE su veća količina<br />

informacija koju SQLCODE nosi, zajedno sa pridruženim poljima u SQLCA. Radi zadovoljenja<br />

SQL standarda, SQLCODE i SQLSTATE se mogu deklarisati kao samostalne<br />

promenljive, bez navodjenja SQLCA strukture. Takva mogućnost se dobija navodjenjem<br />

STDSQL(YES) opcije prekompilatora.<br />

3.2 Konverzija koda greške u tekstualno objašnjenje<br />

Provera kodova i otklanjanje eventualnih grešaka se mogu olakšati ako se izvrši prikaz odgovarajućeg<br />

tekstualnog značenja dobijenog SQLCODE-a (SQLSTATE-a). Takav prikaz se<br />

vrši pozivanjem asemblerskog potprograma DSNTIAR. Primeri poziva ovog programa su<br />

prikazani u programu primer5. U programu primer5a je prikazan rad sa programskom<br />

procedurom koja se može koristiti za proveru ispravnosti izvršenog SQL upita. Detaljan<br />

opis kodova koje vraća DSNTIAR je dat u knjizi Application Programming and SQL<br />

Guide.<br />

3.3 WHENEVER naredba<br />

WHENEVER naredba dopušta programeru da odluči na koji način će proveravati kod<br />

dobijen posle izvršene SQL naredbe. WHENEVER naredba omogućava da DB2 proveri<br />

SQLCA i nastavi izvršavanje programa ili da prenese izvršavanje na druge grane programa<br />

u slučaju da se javila greška ili neko od izuzetih stanja. Tada program 1 može da proveri<br />

odgovarajući kod i preduzme odgovarajuću akciju.<br />

U jednom programu se može navesti više WHENEVER naredbi. Svaka WHENEVER<br />

naredba se odnosi na sve naredne SQL naredbe do navodjenja nove WHENEVER naredbe<br />

sa istim uslovom. Opšti oblik WHENEVER naredbe je:<br />

EXEC SQL WHENEVER uslov akcija;<br />

Postoje tri uslova:<br />

1 REXX ne podržava WHENEVER naredbu.


Otkrivanje grešaka pri aritmetičkim operacijama i konverziji 13<br />

SQLWARNING<br />

SQLEEROR<br />

NOT FOUND<br />

i dve akcije:<br />

CONTINUE<br />

navodi se da bi se odredila akcija u slučaju SQLWARN0=W<br />

ili SQLCODE 100<br />

navodi se da bi se odredila akcija u slučaju da je SQLCODE


Glava 4<br />

Kursori<br />

DB2 koristi mehanizam koji se naziva kursor za dobijanje skupa slogova u aplikativnom<br />

programu. Kursori se mogu koristiti za dobijanje pojedinačnih slogova rezultujućih tabela<br />

ili iz skupa podataka vraćenih od strane stored procedure.<br />

Opšti oblik deklaracije kursora je:<br />

>>--DECLARE--cursor-name--+-----------------------------------+------><br />

+--+-INSENSITIVE----------+--SCROLL-+<br />

+-SENSITIVE---STATIC---+<br />

--CURSOR--+-----------------+------FOR--+-select-statement-+-------><<br />

+-WITH HOLD---|<br />

+-statement-name---+<br />

+-WITH RETURN-+<br />

1) The same clause must not be specified more than once<br />

pri čemu navedeno ime kursora mora da bude jedinstveno u programu.<br />

Ako je navedena SELECT naredba, tada ona ne sme da koristi parametar markere (koriste<br />

se pri radu sa dinamičkim SQL-om), ali može da uključi host promenljive. Host<br />

promenljive koje se javljaju u DECLARE CURSOR naredbi moraju prethodno da budu<br />

deklarisane.<br />

Slučaj kada je umesto SELECT naredbe naveden naziv promenljive koja sadrži upit, koristi<br />

se pri radu sa dinamičkim SQL-om i biće obradjen u poglavlju o dinamičkom SQL-u.<br />

Primeri korišćenja kursora su prikazani u programima primer7 i primer8.<br />

Kursor se koristi za dobijanje podataka, ažuriranje slogova ili brisanje slogova. Ne može<br />

da se koristi za unošenje novih slogova.<br />

Ako se kursor koristi za ažuriranje podataka u kolonama tada na kraju upita treba navesti<br />

klauzulu FOR UPDATE OF sa spiskom imena kolona koje želimo da ažuriramo.<br />

Rezultujuća tabela ne može da se ažurira 1 ako SELECT naredba u deklaraciji kursora:<br />

• ako FROM klauzula spoljašnje select naredbe sadrži<br />

1 U daljem tekstu će se koristiti termin read only tabela.


16 Kursori<br />

– read-only pogled<br />

– tabelu ili pogled koji se javljaju u podupitu spoljašnje select naredbe<br />

– spajanje (tj. ako sadrži više od jedne tabele ili pogleda)<br />

– katalog tabelu koja ne sadrži kolone koje mogu da se ažuriraju<br />

– tabličnu funkciju<br />

• u svom prvom upitu sadrži ključnu reč DISTINCT ili agregatnu funkciju<br />

• spoljašnji podupit sadrži klauzule GROUP BY ili HAVING<br />

• podupit koji se referiše na istu osnovnu tabelu kao i spoljašnji upit.<br />

• klauzule UNION, UNION ALL<br />

• klauzulu ORDER BY (sem kada je kursor deklarisan kao SENSITIVE STATIC)<br />

• sadrži FOR FETCH ONLY ili FOR READ ONLY klauzulu<br />

• ne sadrži FOR UPDATE OF klauzulu, ali se pri izvršavanju naredbe koristi nivo<br />

izolacije UR.<br />

4.1 Rad sa kursorima<br />

4.1.1 Otvaranje kursora<br />

Pre čitanja podataka, kursor mora prethodno da se otvori. Ako deklaracija sadrži<br />

host promenljive, vrednost host promenljive se uzima tek u trenutku otvaranja<br />

kursora. Otvaranje kursora se vrši naredbom<br />

EXEC SQL OPEN ime;<br />

Pomoću otvorenog kursora podaci mogu da se čitaju, da se ažuriraju ili da se brišu.<br />

Takodje, otvoreni kursor može i da se zatvori.<br />

4.1.2 Čitanje podataka kursorom<br />

Čitanje podataka kursorom se vrši naredbom<br />

EXEC SQL FETCH ime INTO :host_promenljiva;<br />

Umesto host promenljive može da se javi host struktura ili lista host promenljivih. Primetimo<br />

da se u deklaraciji kursora nigde ne pojavljuje ključna reč INTO.<br />

Izvršavanjem svake FETCH naredbe čita se red rezultujuće tabele. Ispitivanje da li ima još<br />

podataka u tabeli vrži se testiranjem SQLCODE = 100 (odnosno SQLSTATE=’02000’)<br />

Sem čitanja kursor se koristi i za pozicioniranje na odrejdneni podatak pre ažuriranja ili<br />

brisanja podataka kursorom. Sintaksa FETCH naredbe je prikazana u narednoj tabeli.


Rad sa kursorima 17<br />

+------------------------------------------------------------------------+<br />

| |<br />

| |<br />

| +-NEXT---------------------------+ |<br />

| >>--FETCH----------------------+--------------------------------+----> |<br />

| | (1)| +-PRIOR--------------------------| |<br />

| +-INSENSITIVE----| +-FIRST--------------------------| |<br />

| | (2) | +-LAST---------------------------| |<br />

| +-SENSITIVE------+ +-CURRENT------------------------| |<br />

| | (3) | |<br />

| +-BEFORE-------------------------| |<br />

| | (3) | |<br />

| +-AFTER--------------------------| |<br />

| +-ABSOLUTE---host-variable-------| |<br />

| | +-integer-constant-+ | |<br />

| +-RELATIVE---host-variable-------+ |<br />

| +-integer-constant-+ |<br />

| |<br />

| +-FROM-+ |<br />

| >--------------cursor-name------------------------------------------>< |<br />

| +-| single-fetch-clause +-+ |<br />

| |<br />

| single-fetch-clause: |<br />

|


18 Kursori<br />

Pokušaj otvaranja već otvorenog kursora pri konekciji programa u okviru jednog aplikativnog<br />

servera daje grešku. Iako je oblast važenja kursora program u kome je kursor<br />

deklarisan, svaki paket (ili DBRM plana) koji program formira uključuje posebnu instancu<br />

kursora, pri čemu više instanci jednog istog kursora može biti korišćeno u istom<br />

aplikativnom programu. Npr. neka je program prekompiliran sa opcijom CONNECT(2)<br />

i neka se njegov DBRM koristi za formiranje paketa na lokacijama X i Y. Tada je sledeći<br />

program ispravan<br />

DECLARE C CURSOR FOR ...<br />

CONNECT TO X<br />

OPEN C<br />

FETCH C INTO ...<br />

CONNECT TO Y<br />

OPEN C<br />

FETCH C INTO ...<br />

jer se druga naredba OPEN C referiše na drugu instancu kursora C. Sličan slučaj važi i<br />

za jednu lokaciju ako se koriste paketi koji su u različitim skupovima, i za izbor paketa se<br />

koristi SET CURRENT PACKAGESET naredba.<br />

4.1.3 Ažuriranje podataka kursorom<br />

Kursorom je moguće ažurirati samo slog tabele koji je trenutno pročitan. Zbog toga se<br />

ovakav način ažuriranja tabele naziva poziciono ažuriranje. Takav kursor mora da bude<br />

deklarisan sa FOR UPDATE OF klauzulom. U njoj se navode nazivi svih atributa čiji<br />

sadržaj (u nekom od redova) treba ažurirati. 2 Za ažuriranje se koristi naredba<br />

EXEC SQL UPDATE tabela SET kolona= vrednost, ...<br />

WHERE CURRENT OF ime_kursora;<br />

Posle ažuriranja, kursor i dalje pokazuje na tekući slog. Da bi se pročitao naredni slog<br />

potrebno je izvršiti FETCH naredbu.<br />

Naredba za poziciono ažuriranje tabele zadovoljava sledeće uslove:<br />

• Ne može se ažurirati tabela ako se time narušava neko od ograničenja (jedinstvenost,<br />

check ili referencijalno).<br />

• UPDATE naredbom se ne mogu modifikovati redovi u privremenoj tabeli formiranoj<br />

u istom programu, ali mogu iz deklarisanih privremenih tabela.<br />

• Ako desna strana SET klauzule sadrži potpun SELECT izraz, tada on ne može da<br />

uključuje korelirano ime za tabelu koja se ažurira.<br />

4.1.4 Brisanje podataka kursorom<br />

Kursorom je moguće brisati samo tekući slog tabele (tj. slog koji je pročitan pri poslednjem<br />

izvršavanju FETCH naredbe). Zbog toga se ovakav način ažuriranja tabele naziva<br />

poziciono brisanje. Brisanje se vrši naredbom<br />

2 Sem u slučaju navodjenja opcije prekompilatora STDSQL(YES) odnosno NOFOR.


Rad sa kursorima 19<br />

EXEC SQL DELETE FROM tabela<br />

WHERE CURRENT OF ime_kursora;<br />

Izvršavanjem ove naredbe se briše slog na koji pokazuje kursor. Pri tome važi<br />

• jednim izvršavanjem DELETE naredbe sa opcijom WHERE CURRENT OF briše<br />

se samo jedan red tabele,<br />

• ime kursora u WHERE CURRENT OF odredjuje tabelu iz koje se brišu podaci,<br />

• kursor se ne može koristiti za brisanje podataka iz privremene tabele formirane u<br />

programu, ali može iz deklarisane privremene tabele.<br />

• posle brisanja tekućeg reda kursor ostaje na istom mestu. Jedine naredbe koje mogu<br />

da se izvrše nad tim kursorom su CLOSE i FETCH.<br />

4.1.5 Zatvaranje kursora<br />

Ako je završena obara slogova rezultujuće tabele i potrebno je da se kursor ponovo koristi<br />

tada on mora da se zatvori, a zatim ponovo otvori. Zatvaranje kursora se vrši naredbom<br />

EXEC SQL CLOSE ime; DB2 automatski zatvara sve otvorene kursore na kraju<br />

izvršavanja programa.<br />

4.1.6 Tipovi kursora<br />

Navodjenjem različitih opcija u deklaraciji kursora se definišu kursori različitih tipova.<br />

Deklarisane opcije imaju različite efekte na kursore, i to:<br />

1. Opcija WITH HOLD sprečava zatvaranje kursora pri commit operaciji, sem u sledeća<br />

tri slučaja:<br />

• konekcija asocirana sa kursorom je u release pending stanju,<br />

• važi bind opcija DISCONNECT(AUTOMATIC), ili<br />

• okruženje ne prepoznaje WITH HOLD opciju.<br />

Postojanje WITH HOLD ne sprečava zatvaranje kursora pri izvršavanju rollback<br />

naredbe ili connect(1) operacije.<br />

2. Opcija WITH RETURN opcija označava da kursor koji je deklarisan u stored proceduri<br />

može da vrati rezultat u pozivajući program.<br />

3. Izostanak opcije SCROLL označava da je kursor nepomerljiv u proizvoljnom smeru,<br />

odnosno da njime mogu da se čitaju slogovi strogo sekvencijalno, samo redom, jedan<br />

po jedan od početka ka kraju tabele.<br />

Kursor koji nije pomerljiv se uvek pomera sekvencijalno počev od početka tabele. Po<br />

otvaranju kursor se pozicionira na prvi red u rezultujućoj tabeli. Svako izvršavanje<br />

FETCH naredbe pomera kursor za jedan red prema kraju tabele. Ako se za ovako<br />

definisan kursor izvrše (pozicione) UPDATE ili DELETE naredbe, po njihovom<br />

izvršavanju kursor ostaje na istom (tekućem) redu tabele.


20 Kursori<br />

4. Opcija SCROLLoznačava da je kursor pomerljiv odnosno da se kursorom može vršiti<br />

kretanje u slučajnom redosledu kroz rezultujuću tabelu. Pomerljiv kursor može biti<br />

deklarisan sa atributom INSENSITIVE ili SENSITIVE STATIC.<br />

Navodjenje atributa INSENSITIVE ima slede’ ce efekte:<br />

(a) Veličina, redosled slogova i vrednosti u svakom redu rezultujuće tabele se ne<br />

menjaju posle otvaranja kursora 3 .<br />

(b) Rezultujuća tabela se može koristiti samo za čitanje. Posledica ovoga je da kursor<br />

ne može istovremeno da sadrži klauzule i INSENSITIVE i FOR UPDATE<br />

OF.<br />

Navodjenje atributa SENSITIVE ima slede’ ce efekte:<br />

(a) Rezultat izvršavanja pozicionih UPDATE ili DELETE naredbi je vidljiv u rezultujućoj<br />

tabeli.<br />

(b) Kada tekuća vrednost u redu dalje ne zadovoljava SELECT naredbu iz<br />

deklaracije kursora, takav red prestaje da bude vidljiv u rezultujućoj tabeli.<br />

(c) Kada je red rezultujuće tabele izbrisan iz tabele navedene u deklaraciji kursora<br />

tada takav red prestaje da bude vidljiv u rezultujućoj tabeli.<br />

(d) Promene u tabeli navedenoj u deklaraciji kursora napravljene drugim kursorima<br />

ili od strane drugih aplikacija mogu da postanu vidljive u rezultujućoj tabeli u<br />

zavisnosti od toga da li se koristi FETCH INSENSITIVE ili FETCH SENSIS-<br />

TIVE naredba.<br />

U DB2 V7 deklaracija SENSISTIVE povlači navodjenje klauzule STATIC. Kursori<br />

deklarisani sa STATIC imaju sledeće osobine:<br />

(a) Broj redova u rezultujućoj tabeli se ne menja po otvaranju kursora. Ako je<br />

neki red dodat u tabelu korišćenu u deklaraciji kursora on neće postati vidljiv<br />

u rezultujućoj tabeli.<br />

(b) Uredjnje redova se ne menja po otvaranju kursora. Ako je kursor deklarisan sa<br />

ORDER BY klauzulom, a vrednosti u kolonama navedenim u ORDER BY su<br />

promenjene po otvaranju kursora redosled slogova u rezultujućoj tabeli se neće<br />

promeniti.<br />

Rad sa SENSITIVE kursorima<br />

Posle otvaranja kursor je pozicioniran na prvi red u rezultujućoj tabeli. Pomerljiv kursor se<br />

može pomerati na željeni red navodjenjem apsolutne ili relativne (u odnosu na tekući red)<br />

pozicije u FETCH klauzuli. U narednoj tabeli su prikazane moguće pozicije pomerljivog<br />

kursora.<br />

+------------------------------------------------------------------------+<br />

| Table 4. Positions for a scrollable cursor |<br />

+------------------------------------------------------------------------|<br />

| | Cursor position when the FETCH is |<br />

| Keyword in FETCH statement | executed |<br />

3 Tj. kursor je neosetljiv na promene, npr. od strane drugog aplikativnog programa.


Rad sa kursorima 21<br />

+--------------------------------+---------------------------------------|<br />

| BEFORE | Before the first row |<br />

+--------------------------------+---------------------------------------|<br />

| FIRST or ABSOLUTE +1 | At the first row |<br />

+--------------------------------+---------------------------------------|<br />

| LAST or ABSOLUTE -1 | At the last row |<br />

+--------------------------------+---------------------------------------|<br />

| AFTER | After the last row |<br />

+--------------------------------+---------------------------------------|<br />

| ABSOLUTE(1) | To an absolute row number, from |<br />

| | before the first row forward or from |<br />

| | after the last row backward |<br />

+--------------------------------+---------------------------------------|<br />

| RELATIVE(1) | Forward or backward a relative number |<br />

| | of rows |<br />

+--------------------------------+---------------------------------------|<br />

| CURRENT | At the current row |<br />

+--------------------------------+---------------------------------------|<br />

| PRIOR or RELATIVE -1 | To the previous row |<br />

+--------------------------------+---------------------------------------|<br />

| NEXT or RELATIVE +1 | To the next row (default) |<br />

+------------------------------------------------------------------------|<br />

| Note: |<br />

| |<br />

| 1. ABSOLUTE and RELATIVE are described in greater detail in |<br />

| the discussion of FETCH in Chapter 5 of DB2 SQL Reference. |<br />

+------------------------------------------------------------------------+<br />

Deklaracija kursora sa SENSITIVE klauzulom omogućuje da se promene napravljene od<br />

strane druge aplikacije postanu vidljive u tekućem programu. Da li će se to desiti ili<br />

ne zavisi od navedene klauzule u FETCH naredbi. U narednoj tabeli je prikazan odnos<br />

SENSITIVE i INSENSITIVE klauzula navedenih u deklaraciji tabele i FETCH naredbi.<br />

+------------------------------------------------------------------------+<br />

| Table 5. How sensitivity affects the result table for a scrollable |<br />

| cursor |<br />

+------------------------------------------------------------------------|<br />

| | FETCH sensitivity |<br />

| +------------------------------------------------|<br />

| DECLARE sensitivity | INSENSITIVE | SENSITIVE |<br />

+-----------------------+------------------------+-----------------------|<br />

| INSENSITIVE | No changes to the | Not valid. |<br />

| | underlying table are | |<br />

| | visible in the result | |<br />

| | table. Positioned | |<br />

| | UPDATE and DELETE | |<br />

| | statements using the | |<br />

| | cursor are not | |<br />

| | allowed. | |


22 Kursori<br />

+-----------------------+------------------------+-----------------------|<br />

| SENSITIVE | Only changes that are | All changes are |<br />

| | made by the cursor are | visible in the result |<br />

| | visible in the result | table. |<br />

| | table. | |<br />

+------------------------------------------------------------------------+<br />

Pri radu mogu da nastanu i tzv. rupe u rezultujućoj tabeli. Uzrok njihovog nastajanja je<br />

moguća promena osnovnih tabela od strane istog ili drugog korsinika i rad sa kursoriam<br />

sa odredjenom kombinacijom INSENSITIVE i SENSITIVE klauzula. Rupe se otkrivaju<br />

pojavom ne-nula SQLCODE-a. Više o rupama, načinu njihovog pojavljivnaja i otklanjanja<br />

se može naći u DB2 UDB for OS/390 and z/OS V7 Application Programming and SQL<br />

Guide, SC26-9933-02 u poglavlju 2.2. Takodje, na istom mestu se mogu naći i informacije<br />

kako može da se odredi tip kursora proverom SQLCA.


Glava 5<br />

Pravila za kodiranje SQL naredbi<br />

u PL/I aplikacijama<br />

5.1 Uključivanje SQLCODE i SQLSTATE<br />

PL/I program koji sadrži SQL naredbe mora da uključi:<br />

1. Bar jednu od sledeće dve promenljive:<br />

• SQLCODE deklarisanu kao BIN FIXED(31);<br />

• SQLSTATE deklarisanu kao CHARACTER(5);<br />

2. Ili SQLCA koja sadrži deklaracije promenljivih SQLCODE i SQLSTATE.<br />

Da li će u programu biti deklarisani SQLCODE i SQLSTATE ili SQLCA zavisi od opcije<br />

STDSQL prekompilatora:<br />

YES U ovom slučaju ne treba definisati SQLCA. AKo se SQLCA navede tada se javlja<br />

greška u prekompilaciji. Deklarisana promenljiva SQLSTATE ne sme biti deo strukture.<br />

U ovom slučaju sve deklaracije host promenljivih se moraju javiti u bloku<br />

BEGIN DECLARE SECTION<br />

deklaracije ...<br />

END DECLARE SECTION<br />

U programu može postojati više BEGIN/END sekcija za deklaraciju.<br />

NO U ovom slučaju treba eksplicitno uključiti SQLCA. Za uključivanje deklaracije<br />

SQLCA najbolje je koristiti naredbu EXEC SQL INCLUDE SQLCA.<br />

PL/I programi mogu, uključivanjem naredbe EXEC SQL INCLUDE SQLDA, da uključe<br />

jedno ili više SQLDA polja i iskoriste ih u radu sa dinamičkim SQL-om.<br />

5.2 Pravila kodiranja<br />

Prva naredba u PL/I programima koji koriste SQL mora biti PROCEDURE sa OP-<br />

TIONS(MAIN) osim u slučajevima stored procedura koje mogu biti potprogrami. SQL<br />

naredbe u PL/I programima mogu da se koriste na svim mestima gde i izvršne PL/I


24 Pravila za kodiranje SQL naredbi u PL/I aplikacijama<br />

naredbe. Svaka SQL naredba počinje ključnim rečima ’EXEC SQL’. Pri tome EXEC SQL<br />

mora da se nalazi u jednom redu; ostatak SQL naredbe može ali ne mora da se nalazi<br />

u istom redu gde i EXEC SQL. Kraj SQL naredbe se označava sa ’;’. Tačka-zarez kao<br />

graničnik je neophodan na kraju svake SQL naredbe.<br />

Svaka izvršna SQL naredba može da bude označena labelom na isti način kao i PL/I<br />

naredbe. EXEC SQL INCLUDE naredbe ne mogu da budu ugnježdene. U SQL naredbama<br />

ne treba koristiti direktive PL/I preprocesora.<br />

Komentari mogu da budu uključeni u ugnježdene SQL naredbe na svim mestima gde može<br />

da se nalazi blanko karakter, izuzimajući blankove izmedju EXEC i SQL. Pri tome se komentari<br />

označavaju na isti način kao i u PL/I programima (sa /* i */), uz ograničenje da<br />

komentari ne mogu biti ugnježdeni. Ako se koristi opcija prekompilatora STDSQL(YES)<br />

tada se komentari mogu koristiti i unutar bilo koje statičke SQL naredbe.<br />

Pravila za nastavljanje SQL naredbe su slična pravilima koja važe za naredbe PL/I jezika.<br />

SQL naredba se može pisati u jednom ili više redova. Pri tome, svaka SQL naredba može<br />

biti prekinuta na svakom mestu gde može da se javi blanko karakter (isključujući EXEC<br />

SQL). Ako se programski red završava sa ne-blanko karakterom na desnoj margini, a<br />

sledeći red počinje ne-blanko karakterom na levoj margini, tada se ova dva reda posmatraju<br />

kao jedan (pri čemu se drugi red dopisuje u nastavku prvog). Veličine leve i desne<br />

margine se postavljaju u MARGINS opciji prekompilatora. (inicijalno su 2 i 72).<br />

Pravila koja se odnose na WHENEVER naredbe, i uključivanje deklaracija tabela u program<br />

su prethodno navedena.<br />

5.3 Upotreba host promenljivih<br />

Za upotrebu host promenljivih u PL/I programima važe sledeća pravila:<br />

1. Sve host promenljive se moraju eksplicitno deklarisati pre korišćenja u SQL naredbama,<br />

sem u slučaju upotrebe TWOPASS opcije prekompilatora. Čak i sa<br />

TWOPASS opcijom deklaracije host promenljivih koje se javljaju u naredbi DE-<br />

CLARE CURSOR moraju da prethode samoj naredbi DECLARE CURSOR.<br />

2. Sve host promenljive koje se javljaju u SQL naredbama moraju da imaju dvotačku<br />

kao prefiks.<br />

3. Nazivi host promenljivih treba da budu jedinstveni unutar programa, bez obzira da li<br />

se host promenljive koriste samo u procedurama ili drugim programskim blokovima.<br />

4. Host promenljive moraju biti skalarne promenljive ili strukture komponovane od<br />

skalarnih promenljivih. Host promenljive ne mogu da budu deklarisane kao nizovi.<br />

5. Da bi se izbegle moguće greške pri definisanju imena promenljivih u PL/I programima<br />

treba se pridržavati pravila:<br />

• za imena host promenljivih ne treba koristiti rezervisane reči SQL jezika niti<br />

imena koja počinju sa SQL,<br />

• ne treba koristiti imena eksternih promenljivih ni imena planova koja počinju<br />

sa DSN (DSN je rezervisano za imena koja pripadaju DB2 podsistemu).


Upotreba host promenljivih 25<br />

5.3.1 Deklaracija host promenljivih<br />

Samo neke od mogućih PL/I deklaracija su moguće i za host promenljive. Prekompilator<br />

koristi predefinisane tipove podataka navedene u PL/I default. Ako deklaracija host<br />

promenljive nije korektna, to moze da dovede do poruke ’UNDECLARED HOST VARI-<br />

ABLE’.<br />

Prekompilator koristi jedino imena i atribute promenljivih igonorišući oblast važenja,<br />

memorijske atribute i njihovo smeštanje u memoriji. Tako host promenljive mogu biti klase<br />

STATIC, CONTROLLED, BASED ili AUTOMATIC. Medjutim, ukoliko je promenljiva<br />

deklarisana sa EXTERNAL i STATIC atributima tada mora imati i INITIAL atribut.<br />

U dodatku ?? su prikazani SQL tipovi podataka koje koristi prekompilator za PL/I<br />

deklaracije, kao i preslikavanje izmedju tipova podataka u SQL-u i u PL/I.<br />

5.3.2 Konverzija SQL kodova u tekstualni zapis<br />

Za konverziju dobijenih SQL kodova u tekstualni zapis moze se koristiti asemblerski potprogram<br />

DSNTIAR. Njegovo kodiranje je dato u obliku procedure, a upotreba je prikazana<br />

npr. u programu primer5a.<br />

/**************************************************************/<br />

/* SQL ERROR CODE HANDLING */<br />

/**************************************************************/<br />

greska: proc(por);<br />

dcl (pliretv,dim) builtin;<br />

dcl dsntiar entry options(ASM,INTER,RETCODE);<br />

dcl data_len fixed bin(31) init(120);<br />

dcl data_dim fixed bin(31) init(10);<br />

dcl 1 error_message automatic,<br />

3 error_len fixed bin(15) unal init((data_len*data_dim)),<br />

3 error_text(data_dim) char(data_len);<br />

dcl por char(50) varying;<br />

call dsntiar( sqlca , error_message , data_len );<br />

put file(sysprint) edit(’Greska ’,por) (skip,a,a);<br />

if pliretv = 0<br />

then<br />

do i=1 to dim(error_text,1);<br />

put file (sysprint) edit ( error_text(i)) (skip,a) ;<br />

end;<br />

else<br />

do;<br />

put edit (’Greska pri pozivu DSNTIAR, RC=’, pliretv)<br />

(skip,a,f(10));<br />

stop;<br />

end;<br />

end greska;


Glava 6<br />

Pravila za kodiranje SQL naredbi<br />

u C aplikacijama<br />

Pravila za kodiranje SQL naredbi u C i Java aplikacijama su vrlo sličan već navedenim<br />

pravilma za PL/I.<br />

6.1 Osnovna pravila<br />

Osnovne pravila za kodiranje SQL-a u C programima su:<br />

1. Sve SQL ključne reči (u C programima) moraju da se navode velikim slovima.<br />

2. SQL naredba se može javiti na svim mestima gde i izvršna C naredba.<br />

3. Jedna C naredba može da sadrži najviše jednu SQL naredbu.<br />

4. Svaka SQL naredba koja se kodira u programu mora da počinje sa EXEC SQL. Pri<br />

tome EXEC SQL mora da se nalazi u jednom redu; ostatak SQL naredbe može ali<br />

ne mora da se nalazi u istom redu gde i EXEC SQL; pri tome ostatak naredbe može<br />

da se nalazi u više narednih redova.<br />

5. Kraj SQL naredbe se označava sa ”;”. Tačka-zarez kao graničnik je neophodan na<br />

kraju svake SQL naredbe.<br />

6. Svaka izvršna SQL naredba može da bude označena labelom na isti način kao i C<br />

naredbe.<br />

7. Komentari mogu da budu uključeni u SQL naredbe na svim mestima gde može da<br />

se nalazi blanko karakter, izuzimajući blankove izmedju EXEC i SQL. Pri tome se<br />

komentari označavaju na isti način kao i u C programima (sa /* i */), uz ograničenje<br />

da komentari ne mogu biti ugnježdeni. Kao komentr se može koristiti i // u C<br />

naredbama ali ne i u SQL-u. Ako se koristi opcija prekompilatora STDSQL(YES)<br />

tada se komentari mogu koristiti i unutar bilo koje statičke SQL naredbe.<br />

8. Nastavljanje SQL naredbe: Pravila za nastavljanje SQL naredbe su slična pravilima<br />

koja važe za naredbe C jezika. SQL naredba se može pisati u jednom ili više redova.<br />

Pri tome, svaka SQL naredba može biti prekinuta na svakom mestu gde može da se<br />

javi blanko karakter (isključujući EXEC SQL). Ako se programski red završava sa


28 Pravila za kodiranje SQL naredbi u C aplikacijama<br />

ne-blanko karakterom na desnoj margini, a sledeći red počinje ne-blanko karakterom<br />

na levoj margini, tada se ova dva reda posmatraju kao jedan (pri čemu se drugi<br />

red dopisuje u nastavku prvog). Pri tome ne treba navoditi obrnutu kosu crtu<br />

(backslash) na kraju prvog programskog reda (kao u C-u).<br />

9. Veličine leve i desne margine se postavljaju u MARGINS opciji prekompilatora.<br />

Inicijalne vrednosti su 1 i 72.<br />

10. DB2 prekompilator mora da se izvršava pre C preprocesora. Nijedna od direktiva C<br />

preprocesora nije podržana od strane DB2 prekompilatora.<br />

11. Uključivanje SQL naredbi ili deklaracija (iz ;lana biblioteke) se vrši naredbom<br />

EXEC SQL INCLUDE ime-člana;<br />

12. U slučaju da nekih C karaktera nema na tastaturi na njihovom mestu se mogu<br />

koristiti trigrafi.<br />

Da bi se izbegle moguće greške pri definisanju imena promenljivih u C programima treba<br />

se pridržavati pravila:<br />

• za imena host promenljvih ne treba koristiti rezervisane reči SQL jezika niti imena<br />

koja počinju sa SQL.<br />

• ne treba koristiti imena eksternih promenljvih ni imena planova koja počinju sa DSN<br />

(DSN je rezervisano za imena koja pripadaju DB2 podsistemu).<br />

• Pojam nulls-ova: i C i SQL koriste reč null ali sa različitim značenjem. C jezik<br />

poseduje null karakter (NUL), null pokazivač (NULL) i null naredbu (koja sadrži<br />

samo ;). C NUL je jedan karakter koji poredi jednakost sa 0. C NULL je specijalni<br />

rezervisani pokazivač koji ne pokazuje niti na jedan od važećih objekata. Nasuprot<br />

tome, SQL null vrednost (NULL) je specijalna vrednost koja se razlikuje od svih<br />

ostalih vrednosti i označava odsustvo (nonnull) vrednosti.<br />

6.2 Strukture<br />

Host struktura označava grupno ime više komponenata koje su predstavljene elementarnim<br />

tipovima podataka. Na primer,<br />

struct {char c1[n];<br />

char c2[n];<br />

} polje;<br />

• Polje je naziv host strukture koja se sastoji od elementarnih komponenti c1 i c2.<br />

• n mora biti prethodno definisano kao celobrojna konstanta i mora da poseduje vrednost<br />

¿0.<br />

Host struktura koja je deo druge host strukture može da se referiše jedino u slučaju da se<br />

nalazi na najdubljem nivou ugnježdenja.


Osnovni zahtevi za host promenljive u C-u 29<br />

Strukture u C programima se koriste i za predstavljanje VARCHAR tipa podataka VAR-<br />

CHAR(n) u DB2 predstavlja nisku karaktera čija dužina pripada intervalu [0,n]. VAR-<br />

CHAR tip je podržan u C-u kao niska proizvoljnih (binarnih ili karakter) podataka. Pošto<br />

binarni podaci mogu da sadrže bilo koju (heksadekadnu) kombinaciju VARCHAR tip koristi<br />

dužinu polja i ne poseduje terminator karakter. Na primer,<br />

struct short dužina; char podaci[maxduž] vark;<br />

U prethodnom primeru vark je ime strukture. Promenljive dužina i podaci ne mogu da<br />

budu korišćene pojedinačno, već je celokupna struktura vark prepoznata kao niska karektera<br />

promenljive dužine, gde je maxduž pozitivan ceo broj.<br />

Ova deklaracija je specijalno preslikavanje koje koristi pojedinačni format host strukture.<br />

Ako je potrebna host struktura koja koristi taj format tada se mora definisti drugačije od<br />

VARCHAR tipa podataka deklarisanjem lažnih (dummy) promenljivih unutar strukture.<br />

Primedba: C funkcije za manipulaciju sa stringovima ne mogu da podrže ovaj tip podataka<br />

jer niska može da sadrži NUL karaktere koji ne predstavljaju kraj niske. Praktično,<br />

trenutna dužina niske je upisana u promenljivoj dužina, dok je maxduž maksimalna dužina<br />

niske.<br />

6.3 Osnovni zahtevi za host promenljive u C-u<br />

Osnovni zahtevi za host promenljive u C-u su:<br />

• Sve host promenljive koje se koriste u SQL naredbama moraju biti eksplicitno deklarisane.<br />

Svaki eksplicitna deklaracija koja važi u C-u može se iskoristiti za deklaraciju<br />

host promenljive. Pri tome tip promenljive mora biti kompatibilan sa odgovarajućim<br />

SQL tipom podataka.<br />

• Sve host promenljive koje se koriste u SQL naredbama moraju biti prethodno deklarisane<br />

sem u slučaju da je navedena TWOPASS opcija kod DB2 prekompilatora. Čak<br />

i sa TWOPASS opcijom deklaracije host promenljvih koje se javljaju u naredbi DE-<br />

CLARE CURSOR moraju da prethode samoj naredbi DECLARE CURSOR.<br />

• Deklaracija host promenljivih mora da se nalazi unutar sekcije za deklaraciju<br />

promenljivih:<br />

EXEC SQL BEGIN DECLARE SECTION;<br />

... deklaracije host promenljivih ...<br />

EXEC SQL END DECLARE SECTION;<br />

• Host promenljive ne smeju da se inicijalizuju unutar sekcije za deklaraciju. U programu<br />

se može navesti više sekcija za deklarisanje host promenljivih.<br />

• Host promenljive moraju biti skalarne promenljive ili strukture komponovane od<br />

skalarnih promenljivih; one ne mogu ulaziti u sastav vektora ili nizova osim za nizove<br />

karaktera koje sadrže niske karaktera (stringove). Ako je niz asociran sa host<br />

strukturom tada je dopušteno da on bude niz indikator promenljvih.<br />

• Ako je host promenljiva korišćena u SQL naredbi tada ta SQL naredba mora da<br />

bude unutar oblasti definisanosti te host promenljive.


30 Pravila za kodiranje SQL naredbi u C aplikacijama<br />

6.4 Karakter host promenljive<br />

Prilikom deklaracija karakter host promenljivih mora da se eksplicitno navede dužina<br />

promenljive. Deklaracija ne sme da koristi izraz radi definiasanja dužine karakter<br />

promenljive. U C-u char zauzima jedan bajt u memoriji i nema potrebe za navodjenjem<br />

NUL (x’00’). char[n] predstavlja niz karaktera koji se završava sa NUL. Pošto je<br />

navodjenje dužine u char[n] opciono u C-u, i pošto C kompilator dodaje NUL na kraj<br />

niske sledi da u C-u relno ne postoji koncept karaktera fiksne dužine.


Deo II<br />

Transakcije, restart i oporavak u<br />

programu


Glava 7<br />

Uvod<br />

Sadržaj ovog dela i narednog koji se odnosi na konkurentnost su u velikoj meri isprepletani,<br />

i predstavljaju deo jedne šire oblasti koja se naziva obrada transakcija. Iz čisto praktičnih<br />

razloga izvršena je podela na dve celine. U ovom delu ćemo se posebno koncentrisati na<br />

mogućnost oporavka od greške u programima.<br />

Oporavak (eng. recovery) u bazi podataka označavaju na prvom mestu oporavak same<br />

baze, tj. restauraciju stanja baze do trenutka kada je obezbedjena korektnost njenog<br />

sadržaja. Restauracija se vrši posle svakog dogadjaja koji bazu dovodi u stanje nekonzistentnosti.<br />

Osnovni princip na kome se zasniva oporavak baze je redundantnost.


Glava 8<br />

Transakcije<br />

Transakcija predstavlja logičku jedinicu posla. Razmotrimo sledeći primer: treba podići<br />

novac za žiro računa u banci i uložiti ga na tekući račun. Obe operacije predstavljaju<br />

jednu transakciju. Transakcija je nedeljiva - ne može se desiti da je jedna od njenih komponenti<br />

uspešno završila a druga ne. U slučaju greške kod bilo koje komponente koja ulazi<br />

u transakciju, vrši se poništavanje akcija bilo koje od komponenti te transakcije, koje su<br />

izvršene u okviru te transakcije.<br />

Sistemska komponenta koja obezbedjuje rad sa transakcijama se u RDBMS naziva nadzornik<br />

transakcija (eng. transaction manager). Glavne operacije koje nadzornik izvodi su<br />

potvrda i poništavanje transakcije.<br />

Potvrda transakcije (eng. COMMIT) signalizira uspešan završetak transakcije, i ponovo<br />

uspostavljanje konzistentnog stanja u bazi. Na osnovu toga, sve promene izvršene u<br />

transakciji postaju stalne i dostupne i ostalim korisnicima.<br />

Sintaksa COMMIT naredbe je:<br />

+-WORK-+<br />

>>--COMMIT------+-------+-----------------------------------><<br />

Poništavanje transakcije (eng. ROLLBACK) signalizira neuspešan završetak transakcije.<br />

Radi uspostavljanja (prethodnog) konzistentnog stanja u bazi, sve promene učinjene u ovoj<br />

transkaciji se poništavaju.<br />

Sintaksa ROLLBACK naredbe je:<br />

+-WORK-+<br />

>>--ROLLBACK--+------+--+-------------------------------+---------------><<br />

+-TO SAVEPOINT--+-----------+---+<br />

+-svpt-name-+<br />

Više detalja o transakcijama i oporavku biće u kursu koji se odnosi na administraciju<br />

baze podataka. U ovom trenutku za nas je interesantan oporavak programa u slučaju<br />

neuspešnog završetka transakcije. Opšte pravilo koje treba primenjivati u ovakvim<br />

slučajevima je da sve vrednosti koje su neophodne za restauraciju transakcije treba čuvati<br />

u programskim promenljivima, a ne u bazi podataka. Tipičan primer ove situacije je odnos<br />

transakcija i kursora, kao i postupak za oporavak kursora po završetku transakcije.


36 Transakcije<br />

8.1 Jedinica oporavka i otvoreni kursori<br />

Ako aplikativni program završava jedinicu oporavka (tj. ako je primenjen ili COMMIT<br />

ili ROLLBACK) svi otvoreni kursori se automatski zatvaraju od strane DB2. Izuzetak<br />

predstavlja jedino kursor deklarisan sa WITH HOLD opcijom koji može ostati otvoren<br />

i posle izvršavanja COMMIT naredbe (ali ne i posle ROLLBACK naredbe). Korisnik<br />

može ponovo da otvori kursor ali u tom slučaju obrada počinje od početka tabele. Da<br />

bi se ponovo uspostavila pozicija kursora na sledećem redu od onog na kome se program<br />

nalazio u trenutku COMMIT-a potrebno je koristiti posebnu tehniku.<br />

Primer: Neka je potrebno ažurirati podatke za sve snabdevače koji se javljaju u tabeli snabdevača,<br />

pri čemu je potrebno izvršiti COMMIT na svakih 100 promenjenih ili izbrisanih<br />

redova.<br />

Rešenje je moguće izvesti na sledeći način:<br />

1. Odredi se donja granica vrednosti nekog atributa (koji ima jedinstvene vrednosti) u<br />

tabeli . Neka je to uradjeno za npr. šifru snabdevaca<br />

srbr_min =.... : srbr_min<br />

ORDER BY SRBR;<br />

2. Izvršiti otvaranje kursora i čitanje podataka iz tabele (red po red):<br />

EXEC SQL OPEN IZDKURS;<br />

.<br />

.<br />

.<br />

EXEC SQL FETCH SKURS INTO :srbr, ...<br />

Svaki put kada se izvrši čitanje podataka ažurira se vrednost u host promenljivoj<br />

srbr. Kada program (uspešno) izvrši COMMIT ili ROLLBACK naredbu, potrebno<br />

je vrednost iz srbr-a prepisati u srbr min. Pri sledećem otvaranju kursora, donja<br />

granica uredjene tabele je vrednost sloga koji je već pročitan, tako da se čitaju samo<br />

preostali redovi. U ovom slučaju je vrlo značajno što se vrednost donje granice čuva<br />

u programskoj promenljivoj, a ne promenljivoj baze podataka.<br />

3. Kada se menjaju ili brišu redovi treba koristiti pojedinačne UPDATE ili DELETE<br />

naredbe. Npr za brisanje,<br />

EXEC SQL DELETE FROM S WHERE SRBR = :sifsnabd<br />

ne može se koristiti kursor (DELETE CURRENT) pošto definicija kursora uključuje<br />

ORDER BY klauzulu.


Opšti algoritam 37<br />

Primer ovakvog oporavka je prikazan u programu primer16.<br />

Napomena 3<br />

Ova tehnika ne obezbedjuje i oporavak za ne-DB2 resurse koji se eventualno koriste u<br />

programu, kao npr. sekvencijalne izlazne datoteke, datoteke izveštaja, itd.<br />

8.2 Opšti algoritam<br />

Obično se za kolonu po kojoj se vrši uredjivanje kursora bira primarni ključ. Opšte pravilo,<br />

koje se može primeniti i u slučaju da se primarni ključ sastoji od više komponenti može<br />

se izložiti na sledeći način:<br />

1. Opšti oblik definicije kursora za oporavak i repozicioniranje je<br />

declare c1 cursor for<br />

SELECT ...<br />

FROM ...<br />

WHERE ...nasi predikati...<br />

AND ...predikati za repozicioniranje...<br />

ORDER BY ...kljuc za repozicioniranje...<br />

2. Program u najvećem broju slučajeva ima sledeću strukturu:<br />

if restart then<br />

restauracija promenljivih<br />

do until kraj jedinice posla<br />

open c1<br />

do until sqlstate = ’02000’ or vreme-za-commit /* sqlcode = 100 */<br />

......<br />

end<br />

close c1<br />

commit<br />

cuvanje promenljvih za restart<br />

end<br />

brisanje promenljivih za restart<br />

end /* programa */<br />

3. Zatvaranje i ponovo otvaranje kursora treba da eliminiše slogove koji su već<br />

bili obradjeni. Zbog toga treba prilagoditi deklaraciju kursora na sledeći način<br />

(poslednji ključ predstavlja oznaku za poslednju poznatu donju granicu preostale<br />

uredjene tabele):<br />

(a) Ako se primarni ključ sastoji od samo jedne kolone<br />

declare scan cursor for select .... from ....<br />

where primarni_kljuc > :poslednji_kljuc<br />

order by primarni_kljuc<br />

(b) Ako primarni ključ ima više od jedne kolone (označimo ih sa c1 i c2):<br />

i. Rešenje sa OR (indeksni sken bez uparivanja)


38 Transakcije<br />

declare scan cursor for select ... from ...<br />

where ostali predikati<br />

and (c1 = :poslednji_c1 and c2>:poslednji_c2)<br />

or (c1 > :poslednji_c1)<br />

order by c1, c2<br />

Pristupni put je označen kao indeksni sken bez uparivanja. DB2 će čitati<br />

sve indeksne stranice da bi se pronašli odgovarajući slogovi. Sort nije potreban<br />

ako postoje indeksi na c1 i c2. Ovo rešenje je jako sporo za velike<br />

tabele. Upotreba kursora sa WITH HOLD delimično rešava problem zbog<br />

čuvanja pozicije. Ukoliko se to ne uradi, DB2 skenira kompletan indeks,<br />

pri prvom fetchu, do nailaska na prvi odgovarajući upis u indeksu posle<br />

svakog commit-a.<br />

ii. Rešenje sa AND NOT (indeksni sken sa uparivanjem):<br />

declare scan cursor for select ... from ...<br />

where ostali predikati<br />

and (c1 >= :poslednji_c1)<br />

and not (c1 = :poslednji_c1 and c2=...)<br />

and not (c1 = .... and c2 < ...)<br />

and not (c1 = .... and c2 = ... and c3 < ....)<br />

... .....................<br />

and not (c1 = .... and c2 = ... and c3 = .... and cn =’. Dodatni predikati se dodaju upotrebom OR radi eliminisanja<br />

slogova koji su već bili obradjeni. Broj uparenih kolona (za pretraživanje preko<br />

indeksa) je i dalje ograničen na jedan.<br />

declare scan cursor for select ... from ...<br />

where ostali predikati<br />

and (c1 >= :poslednji_c1)<br />

and (c1 > :poslednji_c1<br />

OR (c1 = :poslednji_c1 and c2 >:poslednji_c2))<br />

order by c1, c2<br />

(d) Rešenje sa više kursora:<br />

declare scan1 cursor with hold<br />

if restart<br />

for select .... open scan2


Tačke čuvanja 39<br />

from ..... do until sqlstate=’02000’<br />

where ostali_predikati fetch scan2<br />

and (c1>:poslednji_c1) ....<br />

order by c1, c2 end<br />

close scan2<br />

declare scan2 cursor with hold<br />

for select .... main:<br />

from ..... do until end<br />

where ostali_predikati open scan1<br />

and (c1=:poslednji_c1 .....<br />

and c2>:poslednji_c2)<br />

end<br />

order by c1, c2<br />

Nedostatak AND NOT rešenja je što ono još uvek ne uparuje obe kolone. To nije<br />

ozbiljan problem ukoliko je broj duplikata u prvoj koloni veliki. Ovaj problem<br />

se može zaobići uvodjenjem više kursora. Na početku otvorimo kursor scan1<br />

koji će vratiti odgovarajući broj redova. Kako koristimo WITH HOLD, ovaj<br />

kursor ce moći da se koristi posle commit-a, jer mu se čuva pozicija. Kada dodje<br />

do commit-a, ne možemo jednostavno da nastavimo da koristimo scan1 jer neće<br />

biti obradjen slog sa vrednostima (C2>poslednji C2 and C1 = poslednji C1).<br />

Stoga moramo da koristimo drugi kursor scan2. Kursor vraća ostale slogove za<br />

C1=poslednji C1. Kada se stigne do kraja kursora (sqlstate=’02000’), nastavljamo<br />

sa korišćenjem scan1. Od svih slučajeva, ovaj je najidelaniji za uparivanje.<br />

8.3 Tačke čuvanja<br />

Alternativan tehnika prethodno opisanim metodama je korišćenje tačaki čuvanja (savepoints).<br />

Tačka čuvanja je mesto unutar logičke jedinice posla na koju se može izvršiti<br />

oporavak relacione baze podatak aposle izvršenih promena. Tačka čuvanja se postavlja<br />

naredbom SAVEPOINT.<br />

Sintaksa naredbe SAVEPOINT je:<br />

+------------------------------------------------------------------------+<br />

| |<br />

| |<br />

| >>--SAVEPOINT--svpt-name---------------------------------------------> |<br />

| +-UNIQUE-+ |<br />

| |<br />

| (1) |<br />

| >--ON ROLLBACK RETAIN CURSORS----------------------------------------> |<br />

| |<br />

| (1) |<br />

| +-ON ROLLBACK RETAIN LOCKS----+ |<br />

| >------------------------------------------------------------------->< |<br />

| |<br />

| Note: |<br />

| (1) These clauses can be specified in either order. |


40 Transakcije<br />

| |<br />

| |<br />

+------------------------------------------------------------------------+<br />

Značenja ključnih reči su:<br />

• svpt-name predstavlja identifikator koji označava tačku čuvanja. Maksimalna dužina<br />

identifikatora je 128 bajtova.<br />

• UNIQUE označava da aplikativni program en može ponovo da koristi ime unutar<br />

jedinice posla. U slučaju da se unutar iste jedinice posla nadju dve tačke čuvanja<br />

sa istim imenom javlja se greška. Ako se ne navede UNIQUE tada navodjenje nove<br />

tačke čuvanja sa istim imenom poništava već postojeću tačku i formira novu.<br />

• ON ROLLBACK RETAIN CURSORS označava da se kursor otvoren posle ove tačke<br />

prekida ne prati i zato ne zatvara pri rollback-u na tu tačku čuvanja. Iako ovakvi<br />

kursori ostaju otvoreni oni mogu da budu i nekorisni (npr. ako je oporavak na tačku<br />

prekida prouzrokovao da se poništi unošenje sloga na koji je kursor pozicioniran,<br />

korišćenje kursora za ažurriranje ili brisanje sloga generiše grešku.<br />

• ON ROLLBACK RETAIN LOCKS označava da se ključevi zahtevani posle tačke<br />

prekida ne prate i zato ne oslobbadajaju pri oporavku na tu tačku prekida.<br />

U okviru jedne aplikacije se može pstaviti proizvoljan broj tačaka čuvanja. Kada tačak v<br />

cuvanja više nije potrebna u aplikaciji ona se briše korišćenjem RELEASE SAVEPOINT<br />

naredbe. Sinataksa RELEASE SAVE POINT naredbe je<br />

+-TO-+<br />

>>--RELEASE---+----+-----SAVEPOINT--svpt-name---------><<br />

Njenim izvršavanjem se briše tačak čuvanja svpt-name i sve tačke čuvanja definisane<br />

posle nje u istoj jedinici posla.<br />

Povratak na neku tačku prekida se vrši naredbom COMMIT TO SAVEPOINT. Ako se<br />

ne navede ime tačke čuvanja vrši se oporavak na poslednju aktivnu tačku.<br />

Korišćenje tačaka čuvanja za poništavanje promena unutar jedinice posla<br />

Kada je aktivna tačka čuvanja nije moguće pristupiti udaljenoj lokaciji korišćenjem trodelnih<br />

imena ili aliasa na ta imena. Medjutim, DRDA pristup može da se koristi uz eksplicitnu<br />

CONNECT naredbu.<br />

Primer: postavljanje tačke čuvanja pri distribuiranoj obradi.<br />

sledeće naredbe:<br />

1. Postavi tačku čuvanja C1<br />

2. Izvršava neku obradu u lokalu<br />

3. Izvrši CONNECT naredbu na udaljeni server<br />

4. Postavi tačku čuvanja C2<br />

Neka aplikacija izvršava<br />

Pošto je tačak C1 postalvjena pre konekcije na udaljeni server, poznata je jedino na<br />

lokalnom serveru. Tačka C2 je postavljena posle konekcije na udlajeni server i poznata je<br />

jedino na tom udaljenom serveru, ali ne i u lokalu.<br />

Tačke čuvanja se automatski oslobadjaju po završetku jedinice posla.


Tačke čuvanja 41<br />

Ograničenja u korišćenju tačaka čuvanja<br />

Tačke čuvanja se ne mogu koristiti u:<br />

1. globalnim transakciama (u RRSAF-u)<br />

2. trigerima<br />

3. korisnički definisanim funkcijama<br />

4. uskladištenim procedurama, korisnički definisanim funkcijama ili trigerima koji su<br />

ugneždeni unutar drugih trigera ili korisnički definisanih funkcija<br />

Detaljnije informacije o SAVEPOINT, ROLLBACK TO SAVEPOINT, i RELEASE<br />

SAVEPOINT naredbama se mogu naći u DB2 SQL, Reference, deo 5.


Deo III<br />

Dodatne programske tehnike


Glava 9<br />

Dinamički SQL<br />

9.1 Uvod<br />

SQL naredbe ugnježdene u viši programski jezik se nazivaju statičke SQL naredbe ako<br />

su u potpunosti odredjene u vreme pisanja programa, i vezane pre izvršavanja programa.<br />

Statičke SQL naredbe se mogu koristiti kada je pre izvršavanja programa poznato koje<br />

SQL naredbe treba izvršiti u aplikaciji.<br />

SQL naredbe ugnježdene u viši programski jezik se nazivaju dinamičke SQL naredbe<br />

ako nisu poznate u vreme pisanja programa. Naredbe dinamičkog SQL-a se pripremaju<br />

za izvršavanje, vezuju i izvršavaju u vreme izvršavanja programa. Postoje četiri tipa<br />

dinamičkog SQL-a:<br />

1. Ugnježdeni dinamički SQL. Aplikacija korisnika upisuje SQL naredbe u host<br />

promenljive i uključuje PREPARE i EXECUTE naredbe kojima zahteva od DB2<br />

pripremu i izvršavanje sadržaja host promenljivih u vreme izvršenja. Programi koji<br />

sadrže ugnježdeni dinamički SQL moraju da se prekompiliraju i vezuju.<br />

2. Interaktivni SQL. U ovu vrstu dinamičkog SQL-a spadaju naredbe koje korisnik unosi<br />

preko SPUFI opcije. Tako unete naredbe DB2 priprema i izvršava kao dinamičke<br />

SQL naredbe.<br />

3. Odloženi dinamički SQL. Naredbe koje pripadaju ovoj grupi nisu ni potpuno statičke<br />

ni potpuno dinamičke. One su ugnježdene u program (kao i statičke naredbe), ali<br />

se pripremaju u vreme izvršenja (kao dinamičke naredbe). DB2 obradjuje odložene<br />

ugnježdene SQL naredbe sa pravilima za vreme vezivanja. Na primer, DB2 koristi<br />

autorizovani ID i kvalifikator koji su odredjeni u vreme vezivanja. Naredbe ove grupe<br />

se koriste za privatni protokol DB2 pri pristupu udaljenim podacima.<br />

4. Dinamički SQL koji se izvršava preko CLI (Call Level Interface) funkcija. CLI pozivi<br />

funkcija koji su sadržani u aplikaciji prenose dinamičke SQL naredbe kao argumente.<br />

Programi koji sadrže CLI naredbe ne moraju da se prekompiliraju i vezuju. Programi<br />

koji sadrže CLI se pišu na C jeziku.<br />

9.2 Izbor izmedju dinamičkog i statičkog SQL-a<br />

Upotreba host promenljivih u velikoj meri povećava fleksibilnost naredbi statičkog SQL-a.<br />

Još veća fleksibilnost naredbi se dobija kada se koristi dinamički SQL. U tom slučaju SQL


46 Dinamički SQL<br />

ista naredba može da radi sa različitim tipovima podataka. Ne može se svaka SQL naredba<br />

izvršavati dinamički. U dodatku ?? su prikazane SQL naredbe i način njihove pripreme.<br />

9.2.1 Šta može da uradi program koji koristi dinamički SQL<br />

Program koji koristi dinamički SQL može da prihvati kao ulaz, ili da formira SQL naredbe<br />

u obliku niske karaktera. U najopštijem slučaju, kada nije poznat tip SQL naredbe koju<br />

treba izvršiti, uobičajeni redosled koraka u izvršavanju je sledeći:<br />

1. Prevesti ulazne podatke, uključujući sve parametar markere u SQL naredbe.<br />

2. Pripremiti SQL naredbe za izvršenje, i zahtevati opis rezultujuće tabele.<br />

3. Rezervisati, u slučaju SELECT naredbe, dovoljno glavne memorije za smeštanje<br />

dobijenih podataka.<br />

4. Izvršiti naredbu ili pročitati redove sa podacima.<br />

5. Obraditi vraćene informacije.<br />

6. Obraditi vraćene SQL kodove.<br />

Ovaj niz koraka se može pojednostaviti ako nije u pitanju SELECT naredba.<br />

9.2.2 Performanse statičkog i dinamičkog SQL-a<br />

SQL naredba zahteva pristupni put za pristup DB2 podacima. U slučaju statičkog SQL-a<br />

koji ne sadrži ulazne host promenljive, DB2 odredjuje pristupni put pri vezivanju programa<br />

ili paketa. Ova kombinacija daje najbolje performanse, jer je pristupni put već<br />

odredjen pri izvršavanju programa.<br />

Ako naredba sadrži statički SQL sa ulaznim host promenljivima, vreme kada DB2 odredjuje<br />

pristupni put zavisi od opcije REOPT(VARS) / NOREOPT(VARS) pri vezivaju.<br />

Ako se navede NOREOPT(VARS) pristupni put se odredjuje pri vezivanju, dok se za<br />

REOPT(VARS) pristupni put odredjuje pri vezivaju, i ponovo pri izvršavanju uzimajući<br />

u obzir konkretne vrednosti host promenljivih, parametar markera i specijalnih registara.<br />

Ova opcija zahteva dodatno vreme za odredjivanje pristupnog puta pri izvršavanju, ali<br />

može dovesti do poboljšanja performansi u slučaju da DB2 odredi značajno bolji pristupni<br />

put.<br />

Za naredbe koje sadrše dinamički SQL, DB2 odredjuje pristupni put u vreme izvršavanja,<br />

odmah posle pripreme naredbe. Ovo je razlog lošijih performansi naredbi sa dinamičkim<br />

SQL-om, ali u slučaju da se ista naredba izvršava veći broj puta može se koristiti keširanje<br />

dinamičkih naredbi radi smanjenja vremena potrebnog za pripremu.<br />

Preporuka je da se za naredbe sa dinamičkim SQL-om koristi REOPT(VARS). U tom<br />

slučaju je potrebno kodirati PREPARE naredbu radi smanjenja overhead-vremena. Sa<br />

REOPT(VARS) DB2 priprema SQL naredbu u isto vreme kada obradjuje OPEN ili<br />

EXECUTE za tu naredbu. Izvršavanje DESCRIBE naredbe pre PREPARE naredbe<br />

ili korišćenje PREPARE naredbe sa INTO parametrom uzrokuje dvostruko izvršavanje<br />

pripreme naredbe (drugi put sa unetim vrednostima promenljivih). Da bi se izbeglo<br />

trošenje vremena na dvostruku pripremu, u naredbama koje koriste kursor, u programu<br />

treba kodirati DESCRIBE naredbu posle OPEN naredbe.


Keširanje naredbi sa dinamičkim SQL-om 47<br />

9.3 Keširanje naredbi sa dinamičkim SQL-om<br />

Cena pripreme naredbi sa dinamičkim SQL-om se može naglo povećati u slučaju učestale<br />

primene COMMIT operacije. U tom slučaju se mora ponovo primeniti PREPARE naredba<br />

da bi se SQL naredba uspešno izvršila. Za SELECT naredbe opcija WITH HOLD može<br />

donekle da ublaži ovaj zahtev, ali zahteva da kursor bude otvoren u vreme COMMIT-a, a<br />

pored toga zadržava i ključeve nad svim objektima od kojih zavisi pripremljena naredba.<br />

DB2 može smanjiti cenu izvršavanja naredbi sa dinamičkim SQL-om ako se pripremljena<br />

dinamička naredba sačuva u kešu. NA taj način se izbegava ponovljena priprema iste<br />

naredbe. Keširane naredbe mogu biti deljene izmedju različitih thread-ova (DB2 niti),<br />

planova ili paketa. Samo naredbe SELECT, UPDATE, INSERT i DELETE mogu da<br />

se keširaju. Medjutim, ako se koristi REOPT(VARS) tada naredbe vezane u takvim<br />

planovima i paketima ne mogu da se keširaju.<br />

Keširanje se omogućuje pri instalaciji DB2. Da bi se naredbe keširale one moraju biti<br />

identične. Pri tome moraju da vaše sledeći uslovi:<br />

• Naredbe koje se keširaju moraju biti identične. Npr. naredbe ’UPDATE DELOVI SET<br />

TEZINA = TEZINA + 10;’ i ’UPDATE DELOVI SET TEZINA = TEZINA + 10 ;’ nisu<br />

identične i za drugu naredbu se ne može koristiti keširana verzija prve.<br />

• Autorizovani ID koji je korišćen pri pripremi prve, mora biti korišćen i pri pripremi<br />

druge naredbe.<br />

• Vrednosti sledećih opcija moraju biti identične pri vezivanju dva paketa u kojima se<br />

nalaze naredbe koje učestvuju u keširanju:<br />

– CURRENTDATA<br />

– DYNAMICRULES<br />

– ISOLATION<br />

– SQLRULES<br />

– QUALIFIER<br />

• Vrednosti specijalnih registara CURRENT DEGREE i CURRENT RULES pri<br />

pripremi druge naredbe moraju biti isti kao i vrednosti pri pripremi prve naredbe.<br />

9.4 Čuvanje pripremljene naredbe posle COMMIT-a<br />

Opcija pri vezivanju KEEPDYNAMIC(YES) dozvoljava čuvanje dinamičkih naredbi posle<br />

commita-a u nekom od procesa. Aplikacija koja je vezana sa ovom opcijom može jednom<br />

da koristi PREPARE naredbu za tu SQL naredbu. Npr.<br />

PREPARE NAREDBA1 FROM ....<br />

EXECUTE NAREDBA1<br />

COMMIT<br />

.<br />

.<br />

.<br />

EXECUTE NAREDBA1


48 Dinamički SQL<br />

COMMIT<br />

.<br />

.<br />

.<br />

9.5 Izbor host jezika za aplikacije sa dinamičkim SQL-om<br />

Programi koji koriste dinamički SQL obično se pišu u assembler-u, C jeziku, PL/I jeziku<br />

i verzijama COBOL jezika koje su različite od OS/VS COBOL-a. Ne-SELECT naredbe i<br />

SELECT naredbe sa fiksnom listom argumenata se mogu pisati u svim host jezicima koje<br />

podržava DB2.<br />

Primeri PL/I programa koji sadrži dinamički SQL se nalaze u<br />

’DSN510.SDSNSAMP(DSNTEP2)’ i ’DBKURS0.T.PLI(DYNSQL)’.<br />

9.6 Dinamički SQL sa ne-SELECT naredbom<br />

Ovaj slučaj predstavlja najjednostavniji način korišćenja dinamičkog SQL-a. Program koji<br />

izvršava ovakve naredbe sa dinamičkim SQL-om mora da uključi sledeće korake:<br />

1. Da uključi SQLCA.<br />

2. Da učita ulaznu SQL naredbu (npr. u nisku karaktera).<br />

3. Da izvrši naredbu. Izvršavanje je moguće na dva načina:<br />

(a) upotrebom EXECUTE IMMEDIATE naredbe, i<br />

(b) upotrebom PREPARE i EXECUTE naredbi.<br />

4. Da obradi SQL greške koje mogu da se jave.<br />

9.6.1 Izvršavanje upotrebom EXECUTE IMMEDIATE<br />

Neka treba učitati sa tastature SQL naredbu kojom se briše red iz tabele DELOVI, i zatim<br />

je izvršiti. Segment PL/I programa koji izvršava ovaj zahtev ima sledeći izgled:<br />

...<br />

dcl niska char(100) var;<br />

...<br />

get(niska); /* npr. niska=’DELETE FROM DELOVI WHERE DRBR=’D9’ */<br />

EXEC SQL EXECUTE IMMEDIATE :niska;<br />

...<br />

9.6.2 Izvršavanje upotrebom PREPARE i EXECUTE<br />

Pretpostavimo da treba izvršiti DELETE naredbu više puta uz upotrebu spiska sa šiframa<br />

delova. U slučaju da ovaj zahtev možemo da pišemo kao statički SQL, njegov izgled bi<br />

bio sledeći:


Dinamički SQL sa ne-SELECT naredbom 49<br />

--cita se vredost DRBR sa tastature u host promenljivu drbr--<br />

DO UNTIL (DRBR = ’**’);<br />

EXEC SQL DELETE FROM DELOVI WHERE DRBR = :drbr;<br />

--cita se vredost DRBR sa tastature u host promenljivu drbr--<br />

END;<br />

Iz ciklusa se izlazi kada se unese ’**’ kao vrednost DRBR. Ukoliko znamo da će se ovakav<br />

upit koristiti samo za tabelu DELOVI, tada možemo da koristimo mnogo efikasniji statički<br />

SQL. Medjutim, ako je ovakav upit potrebno izvršiti i npr. za tabelu POSILJKE, tada<br />

statički SQL ne može da se koristi. Iako host promenljive mogu da sadrže DRBR, one<br />

ne mogu da sadrže ime tabele, tako da ova naredba mora da se izvršava dinamički. U<br />

programu su pored toga nužne i sledeće izmene:<br />

• Umesto host promenljivih koriste se parametar markeri.<br />

• Za pripremu ovakve SQL naredbe koristi se PREPARE.<br />

• Umesto EXECUTE IMMEDIATE koristi se EXECUTE.<br />

Parametar markeri<br />

Umesto host promenljivih u naredbama se zamenjuju parametar markeri, koji su označeni<br />

sa znakom pitanja ?. Tako, umesto prethodne naredbe treba pripremiti naredbu<br />

DELETE FROM DELOVI WHERE DRBR = ?. Svaka host promenljiva se asocira sa parametar<br />

markerom.<br />

PREPARE naredba<br />

Da bi se shvatila suština PREPARE naredbe, može se smatrati da je EXECUTE IM-<br />

MEDIATE razbijeno na dve naredbe: PREPARE i EXECUTE. Prepare naredba prevodi<br />

karakter nisku u SQL naredbu, a EXECUTE je izvršava. Primer: Neka programska<br />

promenljiva niska sadrži ’DELETE FROM DELOVI WHERE DRBR=?’. Da bi se izvršila<br />

njena priprema i pripremljenom obliku dodelilo ime S1, potrebno je izvršiti<br />

EXEC SQL PREPARE S1 FROM :NISKA;<br />

Pripremljena naredba još uvek sadrži parametar marker umesto koga se mora zameniti<br />

vrednost pri izvršavanju naredbe. U pripremljenoj naredbi naziv tabele je fiksan, ali<br />

parametar marker dopušta izvršavanje iste naredbe više puta za različite vrednosti DRBR.<br />

EXECUTE naredba<br />

EXECUTE naredba izvršava prethodno pripremljenu SQL naredbu, pri čemu kao argumente<br />

ima jednu ili više host promenljivih ili host strukturu koja sadrži vrednosti koje<br />

zamenjuju parametar markere. Posle pripreme, ista naredba se može izvršavati više puta<br />

u transakciji. U slučaju da COMMIT ili ROLLBACK unište pripremljenu verziju naredbe,<br />

priprema se mora ponovo izvršiti.<br />

Radi izvršavanja pripremljene naredbe S1, uz upotrebu vrednosti parametra koja je upisana<br />

u promeljivoj SIFRADELA, u programu treba kodirati<br />

EXEC SQL EXECUTE S1 USING :SIFRADELA;


50 Dinamički SQL<br />

Kompletan primer, ekvivalentan prethodno navedenom statičkom, je<br />

--cita se naredba koja sadrzi parametar marker u NISKU --<br />

EXEC SQL PREPARE S1 FROM NISKA;<br />

--cita se vrednost za SIFRADELA --<br />

DO UNTIL (DRBR = ’**’);<br />

EXEC SQL EXECUTE S1 USING :SIFRADELA;<br />

--cita se vrednost za SIFRADELA --<br />

END;<br />

U slučaju da ima više od jednog parametar markera, njihove vrednosti se navode u USING<br />

klauzuli EXECUTE naredbe.<br />

9.7 Dinamički SQL sa fiksnom listom u SELECT naredbi<br />

SELECT naredba sa fiksnom listom vraća red koji sadrži poznat broj vrednosti poznatog<br />

tipa (nije neophodno da se unapred zna broj slogova koji će se dobiti upitom). Kada se<br />

koristi SELECT naredba sa fiksnom listom, unapred je poznat broj i tip host promenljivih<br />

koje treba deklarisati za čuvanje rezultata.<br />

Aplikativni program mora da izvrši sledeće operacije:<br />

1. Da uključi SQLCA<br />

2. Da učita ulaznu SQL naredbu (npr. u nisku karaktera pod imenom NISKA).<br />

Naredba može da sadrži parametar markere.<br />

3. Da deklariše kursor za tu naredbu i dodeli mu ime (npr. C1).<br />

EXEC SQL DECLARE C1 CURSOR FOR NISKA;<br />

4. Da pripremi naredbu za izvršenje:<br />

EXEC SQL PREPARE NAREDBA FROM :NISKA;<br />

5. Da otvori kursor. Otvaranje kursora izračunava vrednost SELECT naredbe koja je<br />

nazvana NAREDBA. Moguća su dva oblika naredbe za otvaranje kursora:<br />

(a) Bez parametar markera<br />

EXEC SQL OPEN C1;<br />

(b) Sa parametar markerima (npr. sa 3 parametar markera):<br />

EXEC SQL OPEN C1 USING :VRED1, :VRED2, :VRED3;<br />

6. Da pročita slogove iz rezultujuće tabele:<br />

EXEC SQL FETCH C1 INTO :TEZINA, GRAD;<br />

Ključna stvar je što je unapred poznat broj i tip host promenljivih koje treba navesti<br />

iza INTO klauzule.


Dinamički SQL sa promenljivom listom u SELECT naredbi 51<br />

7. Da zatvori kursor:<br />

EXEC SQL CLOSE C1;<br />

8. Da obradi SQL greške koje mogu da se jave.<br />

9.8 Dinamički SQL sa promenljivom listom u SELECT<br />

naredbi<br />

SELECT naredba sa promenljivom listom vraća red koji sadrži nepoznat broj vrednosti<br />

nepoznatog tipa. Ovaj slučaj dinamičkog SQL-a se obradjuje uz upotrebu pokazivača.<br />

Aplikativni program mora da izvrši sledeće operacije:<br />

1. Da uključi SQLCA<br />

2. Da učita ulaznu SQL naredbu (npr. u nisku karaktera pod imenom NISKA).<br />

3. Da pripremi i izvrši naredbu. Ovaj korak je mnogo kompleksniji od sličnih koraka<br />

u prethodnim slučajevima. U ovom priručniku će biti naveden samo redosled akcija<br />

koje treba izvršiti. Primeri PL/I programa koji izvršava ovaj oblik SELECT naredbe<br />

se nalaze u<br />

’DBKURS0.T.PLI(DYNSQL)’ i ’DSN510.SDSNSAMP(DSNTEP2)’.<br />

Redosled koraka je sledeći:<br />

(a) Uključivanje SQLDA (SQL descriptor area).<br />

(b) Deklaracija kursora i priprema promenljive naredbe.<br />

(c) Dobijanje informacija o tipu svake kolone u rezultujućoj tabeli.<br />

(d) Odredjivanje veličine memorije potrebne za čuvanje slogova pročitanih podataka.<br />

(e) Otvaranje kursora.<br />

(f)<br />

Čitanje slogova.<br />

(g) Eventualno zatvaranje kursora i oslobadjanje glavne memorije.<br />

U slučaju upotrebe parametar markera, algoritam se dodatno komplikuje.<br />

4. Obrada grešaka koje nastaju pri izvršavanju.<br />

Opis kompletnog postupka za rad sa SELECT naredbom sa promenljivom listom se nalazi<br />

u knjizi Application Programming and SQL Guide.


Glava 10<br />

Podešavanje upita<br />

10.1 Opšta pravila<br />

Ako se upit koga ste napisali sporo izvršava, prvo proverite da li su zadovoljena sledeća<br />

opšta pravila:<br />

1. Da li je upit kodiran na najjednostavniji mogući način? Proverite da li se izdvajaju<br />

nepotrebne kolone i da li postoje ORDER BY ili GROUP BY koji nisu potrebni.<br />

2. Da li su svi predikati korektno kodirani?<br />

• Proverite da li su svi predikati za koje smatrate da treba da budu indeksibilni<br />

zaista i takvi. U knjizi Application Programming and SQL Guide, deo 6.3.3.2,<br />

nalazi se tabela sa spiskom predikata koji mogu da budu indeksibilni.<br />

• Pokušajte da uklonite bilo koji predikat koji je redundantan ili koji vam nije<br />

potreban.<br />

• Proverite da deklarisana dužina bilo koje host promenljive nije veća od dužine<br />

atributa sa kojim se poredi. Ako je veća, tada je predikat u fazi 2 i za njega se<br />

ne može koristiti indeksni sken.<br />

3. Da li postoje podupiti u vasem upitu? Ne postoji apsolutno pravilo po kome bi<br />

odlučivali da li da kodirate podupit ili ne. Opšta pravila su:<br />

• Ako postoji efikasan indeks nad tabelom u podupitu tada je korelirani upit<br />

verovatno najbolji način kodiranja podupita.<br />

• Ako nema efikasnog indeksa nad tabelom u podupitu, tada je verovatno nekorelirani<br />

upit efikasniji.<br />

• Ako postoji više podupita u jednom upitu, poredjajte ih po redosledu efikasnosti.<br />

Npr.<br />

SELECT * FROM POSILJKE<br />

WHERE SRBR IN (Upit 1)<br />

AND DRBR IN (Upit 2)<br />

DB2 izvršava podupite u onom redosledu u kome su navedeni u WHERE<br />

klauzuli. Neka podupit 1 odbacuje 10% od ukupnog broja slogova, a podupit<br />

2 80%. Ako se Predikat u podupitu 1 (označimo ga sa P1) izvršava 1000 puta,


54 Podešavanje upita<br />

tada se predikat u podupitu 2 (označimo ga sa P2) izvršava 900 puta. U obrnutom<br />

redosledu upita P2 bi se izvršavao 1000 puta, ali P1 samo 200 puta, što<br />

u ukupnom zbiru znači 700 provera manje.<br />

Pogledajte deo koji se odnosi na pisanje efikasnijih podupita u okviru ove.<br />

Ako ima sumnje u efikasnost upita treba izvršiti EXPLAIN i kodirati redosled<br />

podupita na osnovu dobijenih rezultata.<br />

4. Da li vaš upit uključuje agregatne funkcije? U tom slučaju proverite da li su one<br />

kodirane na najjednostavniji mogući način.<br />

5. Da li imate ulazne promenljive u predikatu u statičkoj SQL naredbi? Da bi efikasnije<br />

kodirali ovaj slučaj pogledajte u delu o dinamičkom SQL-u kodiranje RE-<br />

OPT(VARS) opciju pri vezivanju.<br />

6. Da li imate problema sa korelacijom kolona? Za dve kolone se kaže da su u korelaciji<br />

ako se njihove vrednosti ne menjaju nezavisno jedna od druge. DB2 ne može da<br />

odredi najbolji pristupni put kada upit sadrži korelirane kolone.<br />

7. Da li upit koristi izraze sa nekolonskim funkcijama? Sledeći predikat kombinuje<br />

kolonu sa vrednostima koje nisu iz kolone na jednoj strani operatora poredjenja:<br />

WHERE KOL + (:hostp1 * KOL)>5000<br />

Isti izraz može biti mnogo efikasnije izračunar ako se napiše na sledeći način:<br />

WHERE KOL > 5000/(1 + :hostp1)<br />

Izraz na desnoj strani se naziva nekolonski izraz. Takve izraze DB2 može da izračuna<br />

mnogo ranije, u fazi 1 i zbog toga ovakvi izrazi traže mnogo manje vremena za<br />

izvršavanje.<br />

10.2 Pisanje efikasnijih predikata<br />

Detaljan opis zavisnosti upita od predikata je dat u knjizi Application Programming and<br />

SQL Guide, u delu 6.3.2. Ovde će biti navedeni samo definicija predikata faze 1 i faze 2.<br />

Redovi koji se dobijaju upitom prolaze kroz dve faze u obradi. Predikatima faze 1 se<br />

nazivaju oni koji se mogu primeniti u prvoj fazi, dok se Predikatima faze 2 nazivaju oni<br />

koji se ne mogu primeniti pre faze 2.<br />

Faza kojoj pripada predikat se može odrediti na osnovu njegove sintakse (već pominjana<br />

tabela koja sadrži podatke i o indeksibilnim predikatima), kao i tipa i dužine konstanti<br />

u predikatu. Svi indeksibilni predikati su predikati faze 1. Preporuka je da se koriste<br />

predikati faze 1 kada god je to moguće.<br />

10.3 Efikasna upotreba podupita<br />

U ovom delu će biti opisana neka od uputstava za efikasnije kodiranje podupita.


Efikasna upotreba podupita 55<br />

10.3.1 Korelirani podupiti<br />

Koreliranim podupitom se naziva upit koji se referiše na najmanje jednu kolonu iz<br />

spoljašnjeg upita. Svi predikati koji sadrže korelirane podupite su predikati faze 2.<br />

Primer: Dobiti imena snabdevača koji isporučuju deo D2.<br />

select sime<br />

from snabdevaci<br />

where exists<br />

( select *<br />

from posiljke<br />

where srbr = snabdevaci.srbr<br />

and drbr = ’D2’ );<br />

Svaki korelirani podupit se izračunava za svaki kvalifikovani red spoljašnjeg upita na koji<br />

se referiše. U prethodnom primeru:<br />

1. DB2 čita red iz tabele snabdevača.<br />

2. Traži vrednost SRBR iz tog reda, u tabeli koja se nalazi u memoriji. U tabeli u<br />

memoriji se nalazi vrednost izvršavanja podupita.<br />

3. Ako vrednost SRBR nije u memoriji, izvršava se podupit.<br />

4. Upisuju se vrednost SRBR i rezultat upita u memoriju.<br />

5. Vraća vrednost tekućeg sloga tabele snabdevaci natrag u aplikaciju.<br />

Ovaj postupak se ponavlja za svaki slog iz tabele snabdevaci.<br />

10.3.2 Nekorelirani podupiti<br />

Nekorelirani upiti su oni koji nemaju reference na spoljašnje upite.<br />

Primer: Dobiti imena snabdevača koji isporučuju deo D2.<br />

select sime<br />

from snabdevaci<br />

where srbr in<br />

( select srbr<br />

from posiljke<br />

where drbr = ’D2’ );<br />

Nekorelirani podupit se izvršava jednom pri otvaranju kursora vezanog za ovaj upit. Akcija<br />

DB2 zavisi od toga da li se kao rezultat vraća jedan ili više slogova.<br />

Ako podupit vraća najviše jedan red, tada su pravila koja se primenjuju radi odredjivanja<br />

u kojoj je fazi predikat koji sadrži unutrašnji upit identična pravilima za pojedinačne<br />

promenljive. Ako pak podupit sadrži više od jednog reda, DB2 pokušava da ga svede na<br />

prethodni slučaj (to je uspešno ako postoji interval poredjenja zajedno sa SOME, ANY<br />

ili ALL). U tom slučaju se, za odredjivanje faze predikata, primenjuju ista pravila kao i<br />

na podupit koji vraća najviše jedan red.


56 Podešavanje upita<br />

10.3.3 Transformacija podupita u spajanje<br />

Podupit može biti transformisan u spajanje izmedju rezultujuće tabele podupita i rezultujuće<br />

tabele spoljašnjeg upita, uz uslov da transformacija ne uvodi redundantnost. DB2<br />

primenjuje ovu transformaciju ako:<br />

1. Podupit se nalazi u WHERE klauzuli.<br />

2. Podupit ne sadrži GROUP BY, HAVING ili agregatne funkcije.<br />

3. Podupit ima samo jednu tabelu u FROM klauzuli.<br />

4. Select lista u podupitu sadrži samo jednu kolonu, za koju jedinstveni indeks garantuje<br />

jedinstvene vrednosti.<br />

5. Operator poredjenja predikata je IN, = ANY ili = SOME<br />

6. Za nekorelirani upit, leva strana predikata je jedna kolona sa istim tipom podataka<br />

i dužinom kao i u koloni podupita.<br />

U izveštaju iz EXPLAIN se informacija da li je podupit transformisan u spajanje<br />

nalazi u koloni QBLOCKNO.<br />

Prethodni upiti sa podupitom mogu da se transformišu u sledeći upit sa spajanjem:<br />

select distinct snabdevaci.sime<br />

from snabdevaci, posiljke<br />

where snabdevaci.srbr = posiljke.srbr<br />

and posiljke.drbr = ’D2’;<br />

10.4 Specijalne tehnike koje utiču na pristupni put<br />

Primedba: naredne tehnike strogo zavise od trenutne verzije DB2. Pri prelasku na novu<br />

verziju softvera, svaku od ovih tehnika treba ponovo proveriti.<br />

10.4.1 Dobijanje informacija o pristupnim putevima<br />

Informacije o pristupnim putevima se mogu dobiti na tri načina:<br />

1. Upotrebom alata Visual Explain.<br />

2. Upotrebom DB2 Performance Monitor-a.<br />

3. Navodjenjem opcije EXPLAIN(YES) pri vezivanju.<br />

10.4.2 Upotreba OPTIMIZE FOR n ROWS<br />

Kada aplikacija izvršava SELECT naredbu, DB2 pretpostavlja da će aplikacija pročitati<br />

sve slogove rezultujuće tabele. Ova pretpostavka je vrlo verovatna u on-line obradama<br />

transakcija ili batch programima. MEdjutim, za interaktivni SQL uobičajeno je da se<br />

definiše upit sa vrlo velikim opsegom slogova koji ga zadovoljavaju, ali se zaista čita samo<br />

prvih nekoliko slogova. U slučaju takvih interaktivnih aplikacija pristupni put DB2 može


Specijalne tehnike koje utiču na pristupni put 57<br />

da ne bude optimalan.<br />

Klauzula OPTIMIZE FOR n ROWS:<br />

• čita samo podskup rezultujućeg skupa,<br />

• daje prioritet čitanju prvih nekoliko slogova.<br />

DB2 koristi ovu klauzulu za izbor pristupnog puta kojim minimizuje vreme odziva za<br />

čitanje prvih nekoliko slogova.<br />

Ova klauzula NE SPREČAVA čitanje svih slogova rezultujuće tabele. Medjutim, ako se<br />

koristi ova klauzula ukupno potrebno vreme može biti značajno veće od vremena koje je<br />

potrebno u slučaju da se ona ne navede.<br />

OPTIMIZE FOR n ROWS se primenjuje samo na upite koji mogu biti primenjeni u<br />

koracima. Ako upit zahteva od DB2 čitanje kompletnog skupa rezultata pre prikazivanja<br />

prvog sloga, ova klauzula se ne primenjuje. Neki od takvih slučajeva su:<br />

• Upit koristi SELECT DISTINCT ili izračunava vredost funkcije samo za jedinstvene<br />

vrednosti, kao u npr. COUNT(DISTINCT ...)<br />

• Koristi se ili GROUP BY ili ORDER BY, pri čemu nema indeksa koji može da<br />

obezbedi željeno uredjenje.<br />

• Postoji agregatna funkcija bez GROUP BY klauzule.<br />

• Upit koristi UNION ili UNION ALL.<br />

10.4.3 Smanjenje broja uparenih kolona<br />

Upotreba indeksa slabih performansi se generalno smanjuje redukovanjem predikata indeksa<br />

koji su upareni sa vodećim kolonama. Smanjenje broja kolona koje su najbolje<br />

uparene može dovesti do različitih efekata u zavisnosti od načina promene predikata.<br />

Promena jednakosnog predikata u BETWEEN predikat<br />

Neka je originalni upit na tabeli KURS<br />

SELECT ....<br />

FROM KURS<br />

WHERE MESTO=’PROJEKTANT’ AND GRAD=’BEOGRAD’<br />

AND NIJEURADIO=’ZAD2’ AND URADIO=’ZAD1’<br />

Neka postoje indeksi indeks1(MESTO, GRAD) i indeks2(NIJEURADIO, URADIO). Posmatrajmo<br />

modifikovani upit:<br />

SELECT ....<br />

FROM KURS<br />

WHERE MESTO BETWEEN ’PROJEKTANT’ AND ’PROJEKTANT’<br />

AND GRAD=’BEOGRAD’<br />

AND NIJEURADIO=’ZAD2’ AND URADIO=’ZAD1’


58 Podešavanje upita<br />

Originalni upit je imao MATCHCOLS 2 (videti kod EXPLAIN-a značenje koje je vezano za<br />

broj ključeva u indeksu koji se koristi za indeksni sken) jer postoje upareni predikati na dve<br />

vodeće kolone u indeksu. Novi upit poseduje MATCHCOLS vrednost 1 zbog BETWEEN<br />

predikata na vodećoj koloni indeksa Indeks1. Indeks2, koji još uvek ima MATHCOLS =<br />

2 će u ovom slučaju biti optimalni pristupni put.<br />

DB2 ne mora da izabere Indeks 2 ako postoji statistika za tabelu KURS. Ako postoji<br />

statistika, izbor pristupnog puta zavisi od filter faktora za predikate MESTO BETWEEN<br />

’PROJEKTANT’ AND ’PROJEKTANT’ i NIJEURADIO=’ZAD2’ AND URADIO=’ZAD1’.<br />

Na sličan način se može onemogućiti upotreba pojedinih indeksa (npr. dodavanjem neutralnog<br />

aritmetičkog predikata, npr. sabiranjem sa 0).<br />

10.4.4 Promena unutrašnjeg u spoljašnje spajanje<br />

Treba eliminisati upotrebu hibridnih spajanja unošenjem unutrašnjeg spajanja u spoljašnje<br />

spajanje, i zatim korišćenjem WHERE klauzule radi eliminacije nepotrebnih slogova.<br />

Primer. Neka želimo da dobijemo rezultate unutrašnjeg spajanja tabela delovi i posiljke:<br />

SELECT DIME, BOJA, DELOVI.DRBR, KOL<br />

FROM DELOVI, POSILJKE<br />

ON DELOVI.DRBR = POSILJKE.DRBR<br />

DB2 će formirati mnogo efikasniji upit sa tabelom delova kao spoljašnjom tabelom u<br />

operaciji spajanja. Da bi se tabela delovi napravila spoljašnjom, treba koristiti operaciju<br />

levog spoljasnjeg spajanja.<br />

SELECT DIME, BOJA, DELOVI.DRBR, KOL<br />

FROM DELOVI LEFT OUTER JOIN POSILJKE<br />

ON DELOVI.DRBR = POSILJKE.DRBR<br />

WHERE DELOVI.DRBR IS NOT NULL;<br />

10.4.5 Ažuriranje statistike u katalogu<br />

Za odredjivanje pristupnih puteva važno je imati ažurnu statistiku u katalogu baze podataka.<br />

Statistika se može ažurirati na dva načina:<br />

1. Ručno. Ovaj način se ne preporučuje zbog mogućnosti eventualnih grešaka koje<br />

mogu negativno da utiču na odredjivanje pristupnog puta.<br />

2. Izvršavanjem RUNSTATS pomoćnog programa i zahtevanjem statistike od koreliranih<br />

kolona W FROM i W NOW. Više reči o RUNSTATS programu biće u kursu<br />

o administraciji baze podataka.


10.5 Osnovno o uskladištenim (stored) procedurama<br />

Uskladištena procedura je prevedeni program, smešten na lokalnom ili udaljenom DB2<br />

serveru, koji može da izvrši SQL naredbe. Tipična uskladištena procedura sadrži dve ili<br />

više SQL naredbe u višem programskom jeziku koje se koriste za obradu. Aplikativni<br />

klijent program koristi SQL naredbu CALL radi poziva uskladištene procedure.<br />

Ove procedure u klijent/server aplikacijama mogu da<br />

• izvrše veliki broj SQL naredbi uz smanjenje saobraća ja kroz mrežu na jednu operaciju<br />

slanja i primanja poruka za niz SQL naredbi.<br />

• pristupaju host promenljivima za koje želite da garantujete sigurnost i integritet.<br />

Da bi uskladištena procedura mogla da se izvršava, mora biti definisana u tabeli<br />

SYSIBM.SYSPROCEDURES. Ova vrsta procedura se može pisati na assembleru, C<br />

jeziku, COBOL-u ili PL/I jeziku. Primeri kodiranja ovih vrsta procedura su dati u<br />

’DSN510.SDSNSAMP’.<br />

Za uskladištene procedure važe sledeća ograničenja:<br />

• Uskladištene procedure mogu da se izvršavaju u DB2 okolini (preko CAF attachment<br />

facilitu) ili u WLM okolini (preko RRSAF attachment facilitu (Recoverable Resuorce<br />

Manager Services).<br />

• U uskladištene procedure ne treba uključivati sledeće SQL naredbe:<br />

– CALL<br />

– COMMIT<br />

– CONNECT<br />

– RELEASE<br />

– SET CONENCTION<br />

– SET CURRENT SQLID<br />

Kada DB2 otkrije ove naredbe menja stanje thread-a u must roll back stanje. Kada<br />

se kontrola vrati pozivajućem programu, on mora da ili uradi ROLLBACK ili da<br />

prekine sa radom, što će prouzrokovati automatski rollback tekuće jedinice posla.<br />

Uskladištene procedure mogu koristiti ili DB2 privatni protokol ili DRDA protokol pri<br />

radu. Ukoliko koristi DRDA protokol, za svaki skup podataka koji želi da se vrati u<br />

pozivajući program procedura mora da deklariše kursor sa opcijom WITH RETURN,<br />

otvori kursor i ostavi ga otvorenog. Procedura se priprema za izvršavanje pomoću sledećeg<br />

niza koraka:<br />

1. Procedura se prekompilira i kompilira.<br />

2. Vrši se linkovanje, pri čemu se bira interfejs modul (CAF ili RRSAF) koji se linkuje<br />

sa procedurom.<br />

3. Svaka procedura se vezuje u paket. Procedura zahteva paket na serveru ali ne i plan.<br />

4. Da bi bila uspešno locirana od srane pozivajućeg programa, procedura se definiše u<br />

tabeli SYSPROCEDURES.


60 Podešavanje upita<br />

5. Potrebno je dati GRANT EXECUTE on PACKAGE .... TO ....; da bi autorizovali<br />

korisnika za izvršavanje paketa.<br />

Procedura se poziva CALL naredbom čiji su argumenti host promenljive deklarisane u<br />

aplikativnom programu. Npr.<br />

EXEC SQL CALL A (:srbr, :status, :sime);<br />

EXEC SQL CALL A (:srbr, :status, ’Jones’);<br />

EXEC SQL CALL :procime (:srbr, :status:, :sime);<br />

Moguće su dve različite konvencije pri linkovanju uskladištenih procedura:<br />

1. SIMPLE: kada ne želimo da pozivajući program prenese NULL vrednosti kao<br />

parametre (niti za slanje niti za primanje).<br />

2. SIMPLE WITH NULLS: kada dopuštamo da pozivajući program prenese NULL<br />

vrednosti kao parametre (bilo za slanje bilo za primanje).<br />

Klijent program koji poziva uskladištene procedure mora biti prekompiliran, kompiliran i<br />

linkovan na klijent sistemu. Uskladištena procedura može biti izvršavana bilo kao glavni<br />

program bilo kao potprogram.<br />

Detaljnije informacije o radu sa uskladištenim procedurama se mogu naći u knjizi Application<br />

Programming and SQL Guide.<br />

10.6 Osnovno o radu sa distribuiranim podacima<br />

Distribuirani podaci su oni koji postoje na nekom sistemu za upravljanje bazama podataka<br />

koji je različit od lokalnog sistema korisnika. Lokalni RSUBP je onaj na kome se vezuje<br />

aplikativni plan. Svi ostali RDBMS-ovi su udaljeni. U daljem tekstu je pretpostavka da<br />

se zahteva servis od udaljenog RSUBP-a. U takvoj situaciji taj RSUBP je server, dok je<br />

lokalni sistem klijent. Aplikacija u jednom trenutku može biti povezana na više servera.<br />

Onaj na kome se trenutno obavlja posao je tekući server.<br />

RSUBP bilo lokalni ili udaljen je poznat DB2 na osnovu naziva svoje lokacije.<br />

lokacija udaljenih RSUBP-a su upisani u komunikacionoj bazi podataka.<br />

Primeri upita koji rade sa udaljenim podacima:<br />

Nazivi<br />

1. SELECT * FROM LOC.DSN8510.EMP; – čitanje udaljene tabele na lokaciji LOC.<br />

2. EXEC SQL CONNECT TO NIŠ; – povezivanje sa serverom na lokaciji NIŠ. Sve<br />

naredne naredbe bi se izvršavale na tom serveru.<br />

3. EXEC SQL CONNECT TO NOVI SAD;<br />

EXEC SQL CALL ime procedure (parametar lista); – poziv uskladištene procedure<br />

na lokaciji NOVI SAD.<br />

Postoje dve metode pristupa:<br />

1. DB2 privatni protokol za pristup (prikazan u primeru 1). Ovaj protokol podržava<br />

jedino DB2 za OS/390.


Osnovno o radu sa distribuiranim podacima 61<br />

2. DRDA pristup (prikazan u primerima 2 i 3). Preporuka je da se koristi DRDA<br />

protokol kada god je to moguće. DRDA protokol pored DB2 za OS/390 podržavaju<br />

i ostali članovi DB2 familije i veliki broj produkata drugih firmi.<br />

Primer. Neka je potrebno napisati program koji ažurira tabelu POSILJKE. Tabela pod<br />

tim nazivom se nalazi na različitim lokacijama (recimo u mestima gde se nalaze skladišta<br />

robe). Grubi izgled programa koji koristi DRDA protokol za pristup udaljenim podacima<br />

je<br />

procitati ulazne vrednosti<br />

DO za sve lokacije<br />

procitaj ime lokacije<br />

EXEC SQL CONNECT TO :lokacija<br />

EXEC SQL UPDATE DBKURS0.POSILJKE<br />

SET KOL = :kol<br />

WHERE SRBR = :srbr<br />

AND DRBR = :drbr<br />

AND PRBR = :prbr;<br />

END;<br />

COMMIT


62 Podešavanje upita<br />

10.6.1 Vezivanje programa koji rade sa DRDA pristupom<br />

• Relevantne opcije prekompilatora su<br />

– CONNECT. Korisiti isključivo CONNECT(2).<br />

– SQL. Koristiti SQL(ALL) eksplicitno ili po default-u ako server nije DB2 za<br />

OS/390. Prekompilator tada prihvata naredbe koje su predvidjene DRDA pravilima.<br />

Ako je server DB2 za OS/390 tada koristiti SQL(DB2).<br />

• Relevantne BIND PACKAGE opcije su:<br />

– naziv lokacije<br />

– SQLERROR<br />

– CURRENTDATA<br />

– OPTIONS. Kada formirate udaljenu kopiju paketa upotrebom BIND PACK-<br />

AGE sa COPY opcijom, upotrebljavajte ovu opciju za kontrolu default opcija<br />

vezivanja koje koristi DB2.<br />

∗ COMPOSITE znači da DB2 koristi opcije navedene u komandi BIND<br />

PACKAGE. Za ostale opcije, koriste se opcije prepisanog paketa.<br />

∗ COMMAND znači da DB2 koristi opcije navedene u komandi BIND PACK-<br />

AGE. Za ostale opcije, koriste se default opcije na serveru na kome se vrši<br />

vezivanje.<br />

• Relevantne BIND PLAN opcije su:<br />

– DISCONNECT. Radi najveće fleksibilnosti koristite DISCONNECT (EX-<br />

PLICIT). To zahteva eksplicitnu upotrebu RELEASE naredbe u vašem programu.<br />

DISCONNECT (AUTOMATIC) raskida sve udaljene veze za vreme COMMIT<br />

operacije, bez potrebe za RELEASE naredbom u programu.<br />

DISCONNECT (CONDITIONAL) raskida sve udaljene veze za vreme COM-<br />

MIT operacije, sem onih sa kojima je asociran kursor otvoren sa WITH HOLD<br />

opcijom.<br />

– SQLRULES. Koristiti SQLRULES(DB2) eksplicitno ili kao default.<br />

– SQLRULES. Koristiti SQLRULES(DB2) eksplicitno ili kao default. SQL-<br />

RULES(STD) primenjuje pravila SQL standarda na CONENCT naredbu, tako<br />

da CONNECT TO loc vraća grešku ako ste već povezani sa lokacijom loc.<br />

– CURRENTDATA. Koristiti CURRENTDATA(NO) da bi forsirali čitanje podataka<br />

u blokovima.<br />

U distribuiranim okruženjima je vrlo vašno koordinirati ažuriranje u dva ili više RSUBPa.<br />

U slučaju da svi sistemi koriste dvofazni commit, ažuriranje se može jednostavno<br />

koordinirati.


EXPLAIN 63<br />

10.7 EXPLAIN<br />

EXPLAIN je alatka koja služi za nadzor i generiše informacije o planovima, paketima ili<br />

vezanim SQL naredbama. Izlaz se upisuje u tabelu pod nazivom PLAN TABLE. Dobijene<br />

informacije mogu da pomognu pri:<br />

• Dizajnu baze, indeksa i aplikativnih programa<br />

• Odredjivanja kada treba ponovo vezati aplikaciju<br />

• Odredjivanju pristupnog puta izabranog za upit.<br />

Primarna funkcija EXPLAIN-a je da prikaže pristupne puteve koji bi se koristili pri<br />

izvršavanju upita. Za UPDATE, INSERT i DELETE WHERE CURRENT OF u tabelu<br />

se upisuje znatno manje informacija.<br />

Da bi se informacije uopšte dobile, potrebno je napraviti tabelu PLAN TABLE. SQL<br />

kojim se formira tabela se nalazi u datoteci ’XDB2000.T.SQL(CRTABPL)’. U ovom<br />

priručniku neće biti detaljno navodjenja značenja svih kolona u rezultatu koji se upisuje<br />

u PLAN TABLE. Umesto toga biće prikazane osnovne vrste pristupnih puteva, dok će<br />

primeri upotrebe EXPLAIN-a biti prikazani na praktičnim vežbama.<br />

Kada se jednom formira tabela planova (plan table) postoje dva pristupa za dobijanje<br />

izlaza iz EXPLAIN-a:<br />

1. BIND/REBIND sa EXPLAIN(YES). DB2 će upisati pristupni put svake opisive<br />

tabele u tabelu planova pri Bind/Rebind procesu plana ili paketa u kome je ukljucena<br />

ova opcija. Rezultat će biti upisan u tabelu sa prefiksom imena koji je jednak<br />

primarnom useridu vlasnika plana/paketa.<br />

2. EXPLAIN FOR ALL SQL naredba. DB2 neće procesirati SQL naredbe kojima je<br />

ovaj tekst, vec će upisati informacije o pristupnim putevima u tabelu. Sintaksa ove<br />

naredbe je<br />

>>--EXPLAIN--+-PLAN-+--+---------------------+-----------------------><br />

+-ALL--+ +-SET QUERYNO=integer-+<br />

>--FOR--explainable-sql-statement-----------------------------------><<br />

10.7.1 Neke informacije o EXPLAIN-u<br />

Postoje dve glavne grupe indikatora za sort, SORTN i SORTC. SORTN sadrži indikator<br />

za nove tabele koji se uvodi u koraku opisivanja, dok je SORTC informacija o rezultatima<br />

prethodnih koraka. Unutar svake grupe postoje četiri moguca razloga za izvršavanje sorta.<br />

Svaki od njih se prikazuje odvojeno.<br />

Agregatne funkcije se mogu obradjivati u različitim koracima izvršavanja SQL-a. Ono sto<br />

želite da se uradi najbrže moguće, je dobijanje podataka. Ako to nije moguće, možda<br />

treba izvršiti sortiranje da bi se podaci dobili u korektnom redosledu. Izračunavanja se<br />

mogu uraditi posle svih ovih koraka.


64 Podešavanje upita<br />

Opcija BIND-a REOPT(VARS) uvodi zahteve za označavanjem kada se informacije iz<br />

opisa pišu, i da li su te informacije važeći pristupni putevi koji se koriste u vreme izvršenja.<br />

WHEN OPTIMIZE označava tip pristupnog puta i da li je on važeći u doba izvršenja. Ako<br />

se koristi REOPT(VARS) i optimizacija u vremenu povezivanja (pri BIND-u) ne uspe zbog<br />

autorizacija ili zavisnosti objekata, u vreme izvršenja se umeće slog u opisu koji to označava<br />

sa vrednošću R u koloni WHEN OPTIMIZE.<br />

TSLOCKMODE daje informaciju o načinu upravljanja zaključavanjima od strane DB2.<br />

Označeni način se dobija na nivou prostora za čuvanje tabela, i činjenica da taj ključ na<br />

nižem nivou može biti tražen se može osmotriti kroz dodatne namere na tom nivou. Ne<br />

može se zahtevati nivo na kome će ostali ključevi biti traženi.<br />

BIND TIME i TIMESTAMP označavaju vreme poslednjeg izvršavanja BIND naredbe. Za<br />

dinamički SQL ove dve vrednosti su jednake.<br />

10.8 Pristupni putevi<br />

10.8.1 Tehnike za poboljšavanje pristupnog puta<br />

Sekvencijalno predčitanje (prefetch)<br />

Izvršavanje skena prostora za čuvanje podataka se vrši po unapred definisanom načinu:<br />

sve stranice podataka se čitaju u nizu u kome se pojavljuju. Ako DB2 startuje I/O za<br />

novu stranicu posle obrade prethodne, program će provesti dosta vremena na čekanje<br />

tako čitanih stranica. Za rešavanje ovog problema se uvodi asinhroni mehanizam: čitanje<br />

velikog broja redova unapred. Dok se vrši obrada jedne stranice, sledeća se već nalazi<br />

u memoriji. Ovaj mehanizam dovodi do velikog poboljšanja performansi, pri čemu se u<br />

velikoj meri smanjuje i broj zahtevanih I/O operacija.<br />

Ako je veličina bufferpool-a u kome se nalazi vaš objekat manja od 10.000 stranica, DB2 će<br />

biti u mogućnosti da čita stranice u bufferpool-u koristeći efikasne I/O operacije i čitajući<br />

32 stranice u jednoj I/O operaciji. Kako se čita 32 stranice za popunjavanje svih 1000<br />

stranica trebaće najviše 31 I/O operacija, umesto ranijih 1000.<br />

Postoje dve tačke u kojma DB2 može da odluči da koristi sekvencijalno predčitanje: u<br />

vreme bind-ovanja i u vreme izvršenja. Prvo se naziva sekvencijalno predčitanje, dok se<br />

drugo naziva sekvencijalna detekcija. U obe tehnike se primenjuje isti osnovni princip -<br />

predpročitani podaci se mogu koristiti samo ako ste sigurni da će se obradjivati dovoljno<br />

veliki broj stranica da opravda cenu predčitanja.<br />

Predčitanje se može prevesti u veliki broj stranica za pristup indeksom, i clusterratio za<br />

uzastopne pristupe podacima. Primetimo da postoji samo jedno polje za naznačavanje<br />

predčitanja zbog čega se ne može napraviti razlika izmedju predčitanja indeksa i podataka.<br />

Triger-in kod sekvencijalne detekcije se radi na osnovu naredbe koja se izvršava. DB2<br />

vodi računa o pristupu na poslednjh 8 stranica. Ako je paterna dovoljno sekvencijalna,<br />

DB2 počinje sa asinhronim I/O. Ova tehnika se takodje može primeniti na UPDATE i<br />

DELETE.<br />

EXPLAIN neće označiti ništa što zavisi od karakteristika u vreme izvršenja, bez obzira<br />

da li je predčitanje trigerovano ili ne.


Pristupni putevi 65<br />

List Prefetch<br />

• dohvata sve pokazivače indeksa koji zadovoljavaju uparujući predikat.<br />

• Sortira pokazivače u opadajući redosled.<br />

• Pristupa stranicama podataka upotrebom liste pokazivača (korišćenjem Skip Sequential<br />

Access Method-a).<br />

• Ova tehnika je korisna kada je Clusterratio 80% samo kada je potreban mali broj stranica.<br />

• Uvek se koristi za<br />

– Multiple index access<br />

– Inner table access of a hybrid Join<br />

Kao što je prethodno napomenuto, moguće je da niz slogova u TS ne odgovara nizu indeksa,<br />

što uzrokuje čitanje iste strane podataka više puta. Sortiranjem odgovarajućeg<br />

RID-a u opadajući redosled problem se eliminiše.<br />

Skip sequential access method moze da pročita ne-uzastopne stranice u jednoj I/O operaciji.<br />

Mana ove tehnike je što mora da se čeka na prvi slog sve dok RID ne bude<br />

pročitan i sortiran, što može da bude neprihvatljivo kod interaktivnih programa.<br />

Thresholds (prag, granica) kod List Prefetch-a<br />

DB2 ima granicu i u vreme povezivanja i u vreme izvršenja kada proverava da li je<br />

predčitanje liste dobro rešenje. Najveća opasnost je da se završi sa RID listom koja<br />

sadrži najveći deo slogova, sortira se a da pri tome bude pročitan najveći deo stranica u<br />

TS-u. U tom slučaju efikasnije je primeniti jednostavni sken TS-a.<br />

DB2 poseduje mogucńost da zaobidje particije u podeljenom TS, kada je očigledno da<br />

particija ne sadrži tražene slogove. Ovo može da se primeni na pristupne puteve za indeks<br />

i TS.<br />

Particioni sken<br />

Particioni sken obezbedjuje mogućnost za skeniranje odgovarajućih podataka bez upotrebe<br />

indeksa particije. Na taj način se mogu eliminisati nepotrebna skeniranja TS-a i zameniti<br />

sa pristupnim putem koji pristupa samo zahtevanim particijama.<br />

Odluka koje su particije potrebne se donosi u vreme BIND-a. Da bi se naredbe sa host<br />

promenljivim načinile odgovarajucim za particioni sken, REOPT(VARS) opcija mora biti<br />

upotrebljena za odlaganje BIND-a u vreme izvršenja.<br />

Particije mogu da barataju ne-neprekidnim particijama kada se koristi npr. IN lista.<br />

Takodje, particioni sken uzima jedino prvu kolonu particionog ključa u razmatranje, čak<br />

i ako je upareno više kolona tog indeksa.<br />

10.8.2 Pristupni putevi za jednu tabelu<br />

U narednim primerima će za ilustraciju različitih vrsta pristupnih puteva biti korišćene<br />

tabele T adress i R postal code. U T adress indeks se javlja na R ADDRESS, (T STREET,<br />

T NUMBER), T NAME, i R OWNER. U R postal code indeks se javlja na R POSTAL CODE.


66 Podešavanje upita<br />

1. Upit<br />

select * from t_address<br />

where R_POSTAL_CODE=’1234’<br />

za koji je sadržaj polja ACCESSTYPE u PLAN TABLE ’R’, se obradjuje na sledeći<br />

način:<br />

2. Upit<br />

• pošto nema indeksa nad tom kolonom, mora da se primeni tablespace scan<br />

• u segmentiranom TS DB2 će skenirati samo one segmente koji sadrže podatke,<br />

a u prostom TS sa više od jedne tabele biće procitane sve stranice.<br />

select * from t_address<br />

where T_street = ’Vase Carapica’<br />

za koji je sadržaj polja ACCESSTYPE u PLAN TABLE ’I’, se obradjuje tako što<br />

indeksni sken sa uparivanjem koristi kolone u indeksu radi odredjivanja redova koji<br />

zadovoljavaju uslov. Strane u TS će biti čitane jedino ako je u indeksu pronadjen<br />

odgovarajući red. Ova metoda je vrlo korisna za velike tabele, dok za male tabele<br />

prednosti nisu tako izražene.<br />

3. Upit<br />

select * from t_address<br />

where T_number = 88<br />

za koji je sadržaj polja ACCESSTYPE u PLAN TABLE ’I’ se obradjuje na sledeći<br />

način:<br />

Pretpostavimo da indeksni sken sa uparivanjem ne može da se koristi, ali je broj<br />

stranica u indeksu znatno manji nego u TS, i tražena kolona se nalazi u indeksu. U<br />

ovom slučaju se kao koristan moze pokazati indeksni sken bez uparivanja. DB2 će<br />

čitati i obraditi sve stranice koji su listovi u indeksu. Da bi se ubrzao proces, DB2 ce<br />

verovatno korisiti sekvencijalni prefetch (u daljem tekstu sekvencijalno predčitanje).<br />

4. Upit<br />

select t_street, t_number<br />

from t_address<br />

where t_street = ’Vase Carapica’<br />

and t_number in (1,2)<br />

se obradjuje preko IN-list indeks skena (polje ACCESSTYPE u<br />

PLAN TABLE je ’N’).<br />

Ova pristupna metoda je specijalni slučaj indeksnog skena sa uparivanjem. Za<br />

svaku vrednost u in-listi, DB2 će koristiti indeksni sken sa uparivanjem za odredjivanje<br />

redova koji zadovoljavaju uslov. DB2 poseduje mogućnost da konvertuje skup<br />

predikata kombinovan kroz OR u ovaj tip pristupnog puta. Izlaz iz opisa ce naznačiti<br />

šta se desilo.


Pristupni putevi 67<br />

5. Upit<br />

select *<br />

from t_address<br />

where (t_name = ’Pera’)<br />

or (t_street = ’Vase Carapica’)<br />

za koji je sadržaj polja ACCESSTYPE u PLAN TABLE ’M’ (sa kombinacijama MX,<br />

MU, ...) se obradjuje preko višestrukog indeksnog pristupa (multiple-index access).<br />

DB2 može da koristi više od jednog indeksa pri formiranju skupa odgovora. Mehanizam<br />

je vrlo jednostavan. Izabira se RID (Row ID) kvalifikovanog sloga u svakom indeksu,<br />

i kombinuju rezultati svakog indeksa korišćenjem i/ili za odredjivanje konačne<br />

liste RIDova. Ova lista se koristi za pristup stranicama podataka.<br />

6. Upit<br />

select min(t_number)<br />

from t_address<br />

where t_street = ’Vase Carapica’<br />

se obradjuje kao pristup sa jednim čitanjem. Ovo je verovatno najbrži mogući pristupni<br />

put. DB2 čak ne mora da skenira ni indeks. Izdvaja se jedna stavka iz indeksa<br />

i dobija rezultat upita.<br />

7. Upit<br />

select *<br />

from t_address<br />

where t_number = 88<br />

se obradjuje primenom neuparenog predikata na indeks. Ova metoda se naziva<br />

zaklanjanje (zaštita) indeksa. Ona je alternativa primeni predikata u vreme pristupa<br />

podacima. Postoje izvesna ograničenja mogucnosti DB2 da tako uradi. Čak i ako<br />

postoje predikati u polju koji su prisutni u indeksu, ali nisu upareni, DB2 će primeniti<br />

ove uslove u vreme pristupa podacima. Takodje, DB2 ne može da koristi ovu tehniku<br />

pri list-prefetching-u.<br />

10.8.3 Pristupni putevi za više tabela<br />

Za pristup do više tabela postoje tri kombinovane tehnike: Ugnježdena petlja (Nested<br />

loop), Pomešani sken (Merge scan) i Hibridno spajanje (hybrid join).<br />

Ako se kombinuju dve ili više tabela, DB2 može da koristi različite tehnike za kombinovanje<br />

prve dve i treće od njih. DB2 takodje može da koristi bilo koji od metoda pristupa<br />

pojedinačnim tabelama da bi ih obradio.


68 Podešavanje upita<br />

Ugnježdena petlja<br />

SELECT T_NAME, T_STREET, T_CITY<br />

FROM T_ADDRESS A, R_POSTAL_CODE B<br />

WHERE T_FAX_NR LIKE ’03%’<br />

AND A.R_POSTAL_CODE = B.R_POSTAL_CODE<br />

Unutrašnja tabela se skenira da bi se pronašli svi slogovi koji se mogu upariti sa slogovima<br />

spoljašnje tabele. Rezultat ovoga je jedan sken spoljašnje tabele i n-skenova (n = broj<br />

odgovarajućih slogova unutrašnje tabele) unutrašnje tabele. Efikasnost ove tehnologije<br />

jako zavisi od efikasnosti skena unutrašnje tabele.<br />

Spajanje sa pomešanim skenom<br />

SELECT T_NAME, T_STREET, T_CITY<br />

FROM T_ADDRESS A, R_POSTAL_CODE B<br />

WHERE T_FAX_NR LIKE ’03%’<br />

AND A.R_POSTAL_CODE = B.R_POSTAL_CODE<br />

AND T_CITY LIKE ’A%’<br />

- Sken T_ADDRESS - Skenira se R_POSTAL_CODE<br />

- Dohvataju se slogovi - Dohvataju se slogovi koji<br />

koji imaju T_FAX_NR like ...<br />

imaju T_CITY like<br />

- Uredjuje se rezultat po R_POSTAL_CODE - Uredjuje se rezultat po<br />

R_POSTAL_CODE<br />

spajaju se dve tabele<br />

Obe tabele se uredjuju u redosled po kolonama koje se spajaju preko sortiranja indeksa.<br />

DB2 zatim počinje balansirano čitanje obe tabele.<br />

Hibridno spajanje<br />

SELECT T_NAME, T_STREET, T_CITY<br />

FROM T_ADDRESS A, R_POSTAL_CODE B<br />

WHERE T_FAX_NR LIKE ’03%’<br />

AND A.R_POSTAL_CODE = B.R_POSTAL_CODE<br />

• skenira se spoljašnja tabela<br />

• formira se medjutabela dodavanjem odgovarajućeg RID-a u spoljašnju rezultat<br />

tabelu<br />

• ako unutrašnja tabela nije visoko klasterovana, potreban je radni prostor za sortiranje<br />

• lista predčitanja unutrašnje tabele<br />

• dopisivanje rezultata


Pristupni putevi 69<br />

Hibridno spajanje je na neki način različita tehnika koja pokušava da reši problem<br />

ugnježdene petlje: skeniranje unutrašnje tabele je primenjeno za svaki slog spoljašnje<br />

tabele koji zadovoljava uslov. DB2 ekstrahuje RID unutrašnje tabele jednom za svaku<br />

različitu vrednost u unutrašnjoj tabeli. Zatim se medjurezultat uredjuje po RID-ovima<br />

unutrašnje tabele, i predčitanje liste se koristi za pristup dodatnim informacijama. DB2<br />

zahteva najmanje jedan indeks na kolonama unutrašnje tabele koje se spajaju da bi ova<br />

tehnika mogla da se koristi.<br />

Kada se primenjuje koja tehnika<br />

Procena DB2 jako zavisi od tačnosti procene spajanja kolona. Vrlo je važno da DB2<br />

poseduje korektnu statistiku za kolone koje se koriste pri spajanju tabela.<br />

• Ugnježdena petlja. Sken unutrašnje tabele je jako skupa operacija. Ugnježdena<br />

petlja će se primeniti ako mali broj slogova spoljašnje tabele zadovoljava uslov, ili<br />

ako postoji vrlo efikasan indeks nad unutrašnjom tabelom. Vrlo mala spoljašnja<br />

tabela će takodje poboljšati performanse.<br />

• Pomešani sken. Ugnježdena petlja skenira unutrašnju tabelu, čak i za duplikate.<br />

Veliki broj duplikata u obe tabele se bolje obradjuje sa tehnikom pomešanih skenova,<br />

kao i velike tabele bez odgovarajućih indeksa.<br />

• Hibridno spajanje. Najbolji efekti se dobijaju ako postoji indeks na atributima<br />

unutrašnje tabele preko kojih se vrši spajanje, kao i ako spoljašnja tabela ima veliki<br />

broj duplikata.<br />

• Spoljašnje spajanje. DB2 interno prevodi desno spoljašnje spajanje na levo spoljašnje<br />

spajanje. U oba slučaja JOIN TYPE je ’L’. Puno spoljašnje spajanje ima ’F’ u<br />

JOIN TYPE koloni, i uvek se obradjuje primenom tehnike pomešanih skenova.


Glava 11<br />

Literatura<br />

11.1 DB2 za OS/390 V7<br />

1. DB2 UDB for OS/390 and z/OS V7 Administration Guide, SC26-9931-02<br />

2. DB2 UDB for OS/390 and z/OS V7 Application Programming and SQL Guide,<br />

SC26-9933-02<br />

3. DB2 UDB for OS/390 and z/OS V7 Application Programming Guide and Reference<br />

for Java(TM), SC26-9932-02<br />

4. DB2 UDB for OS/390 and z/OS V7 Command Reference, SC26-9934-02<br />

5. DB2 UDB for OS/390 and z/OS V7 Data Sharing: Planning and Administration,<br />

SC26-9935-02<br />

6. DB2 UDB for OS/390 and z/OS V7 Image, Audio, and Video Extenders Administration<br />

and Programming, SC26-9947-00<br />

7. DB2 UDB for OS/390 and z/OS V7 Installation Guide, GC26-9936-02 DSNIGH12<br />

8. DB2 UDB for OS/390 and z/OS V7 Messages and Codes, GC26-9940-02 DSN-<br />

MCH12<br />

9. DB2 UDB for OS/390 and z/OS V7 Net Search Extender Administration and Programming,<br />

SC27-1171-00<br />

10. DB2 UDB for OS/390 and z/OS V7 ODBC Guide and Reference, SC26-9941-02<br />

11. DB2 UDB for OS/390 and z/OS V7 Reference for Remote DRDA Requesters and<br />

Servers, SC26-9942-00<br />

12. DB2 UDB for OS/390 and z/OS V7 Release Planning Guide, SC26-9943-02<br />

13. DB2 UDB for OS/390 and z/OS V7 SQL Reference, SC26-9944-02<br />

14. DB2 UDB for OS/390 and z/OS V7 Text Extender Administration and Programming,<br />

SC26-9948-00<br />

15. DB2 UDB for OS/390 and z/OS V7 Utility Guide and Reference, SC26-9945-03


16. DB2 UDB for OS/390 and z/OS V7 XML Extender Administration and Programming,<br />

SC26-9949-00<br />

17. DB2 UDB for z/OS and OS/390 V7 What’s New?, GC26-9946-02<br />

11.2 QMF V7R2 for OS/390<br />

1. QMF Developing QMF Applications Version 7 Release 2, SC27-0718-01<br />

2. QMF Getting Started with QMF for Windows Version 7 Release 2, SC27-0723-01<br />

3. QMF High Performance Option User’s Guide for z/OS and OS/390 Version 7 Rel 2,<br />

SC27-0724-01<br />

4. QMF Installing & Managing QMF for Windows Version 7 Release 2, GC27-0722-01<br />

5. QMF Installing and Managing QMF Version 7 Release 2, GC27-0720-01<br />

6. QMF Introducing QMF Version 7 Release 2, GC27-0714-02<br />

7. QMF Messages and Codes Version 7 Release 2, GC27-0717-01<br />

8. QMF Reference Version 7 Release 2, SC27-0715-01<br />

9. QMF Using QMF Version 7 Release 2, SC27-0716-01<br />

11.3 Dodatna literatura<br />

1. N. Mitić, plikativno programiranje za DB2 V5 za OS/390, Beograd 1999.


Dodatak A<br />

Značenja polja u SQLCA<br />

Napomena 4<br />

Imena koja se odnose na FORTRAN su isključena zbog preglednosti.<br />

+----------------------------------------------------------------------+<br />

| Table 31. Fields of SQLCA |<br />

+----------------------------------------------------------------------|<br />

| Assembler, | | | |<br />

| COBOL, or | C | Data | |<br />

| PL/I Name | Name | Type | Purpose |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLCAID | sqlcaid | CHAR(8) | An "eye catcher" for |<br />

| | | | storage dumps, containing |<br />

| | | | the text ’SQLCA’. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLCABC | sqlcabc | INTEGER | Contains the length of the |<br />

| | | | SQLCA: 136. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLCODE | SQLCODE | INTEGER | Contains the SQL return |<br />

| (See note | | | code. (See note 2) |<br />

| 1) | | | Code Means |<br />

| | | | 0 Successful |<br />

| | | | execution |<br />

| | | | (though there |<br />

| | | | might have |<br />

| | | | been warning |<br />

| | | | messages). |<br />

| | | | positive Successful |<br />

| | | | execution, but |<br />

| | | | with an |<br />

| | | | exception |<br />

| | | | condition. |<br />

| | | | negative Error |<br />

| | | | condition. |<br />

+------------+--------------+-------------+----------------------------|


74 Značenja polja u SQLCA<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRML | sqlerrml | SMALLINT | Length indicator for |<br />

| (See note | (See note 3) | | SQLERRMC, in the range 0 |<br />

| 3) | | | through 70. 0 means that |<br />

| | | | the value of SQLERRMC is |<br />

| | | | not pertinent. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRMC | sqlerrmc | VARCHAR(70) | Contains one or more |<br />

| (See note | (See note 3) | | tokens, separated by |<br />

| 3) | | | X’FF’, that are |<br />

| | | | substituted for variables |<br />

| | | | in the descriptions of |<br />

| | | | error conditions. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRP | sqlerrp | CHAR(8) | Provides a product |<br />

| | | | signature and, in the case |<br />

| | | | of an error, diagnostic |<br />

| | | | information such as the |<br />

| | | | name of the module that |<br />

| | | | detected the error. In |<br />

| | | | all cases, the first three |<br />

| | | | characters are ’DSN’ for |<br />

| | | | DB2 for MVS/ESA. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(1) | sqlerrd[0] | INTEGER | Contains an internal error |<br />

| | | | code. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(2) | sqlerrd[1] | INTEGER | Contains an internal error |<br />

| | | | code. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(3) | sqlerrd[2] | INTEGER | Contains the number of |<br />

| | | | rows affected after |<br />

| | | | INSERT, UPDATE, and DELETE |<br />

| | | | (but not rows deleted as a |<br />

| | | | result of CASCADE delete). |<br />

| | | | Set to 0 if the SQL |<br />

| | | | statement fails, |<br />

| | | | indicating that all |<br />

| | | | changes made in executing |<br />

| | | | the statement were |<br />

| | | | canceled. Set to -1 for a |<br />

| | | | mass delete from a table |<br />

| | | | in a segmented table |<br />

| | | | space. |<br />

+------------+--------------+-------------+----------------------------|


75<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(4) | sqlerrd[3] | INTEGER | Contains timerons, a short |<br />

| | | | floating-point value that |<br />

| | | | indicates a rough relative |<br />

| | | | estimate of resources |<br />

| | | | required (See note 4). It |<br />

| | | | does not reflect an |<br />

| | | | estimate of the time |<br />

| | | | required. When preparing |<br />

| | | | a dynamically defined SQL |<br />

| | | | statement, you can use |<br />

| | | | this field as an indicator |<br />

| | | | of the relative cost of |<br />

| | | | the prepared SQL |<br />

| | | | statement. For a |<br />

| | | | particular statement, this |<br />

| | | | number can vary with |<br />

| | | | changes to the statistics |<br />

| | | | in the catalog. It is |<br />

| | | | also subject to change |<br />

| | | | between releases of DB2 |<br />

| | | | for MVS/ESA. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(5) | sqlerrd[4] | INTEGER | Contains the position or |<br />

| | | | column of a syntax error |<br />

| | | | for a PREPARE, or EXECUTE |<br />

| | | | IMMEDIATE statement. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLERRD(6) | sqlerrd[5] | INTEGER | Contains an internal error |<br />

| | | | code. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN0 | SQLWARN0 | CHAR(1) | Blank if all other |<br />

| | | | indicators are blank; |<br />

| | | | contains W if at least one |<br />

| | | | other indicator also |<br />

| | | | contains W. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN1 | SQLWARN1 | CHAR(1) | Contains W if the value of |<br />

| | | | a string column was |<br />

| | | | truncated when assigned to |<br />

| | | | a host variable. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN2 | SQLWARN2 | CHAR(1) | Contains W if null values |<br />

| | | | were eliminated from the |<br />

| | | | argument of a column |<br />

| | | | function; not necessarily |<br />

| | | | set to W for the MIN |<br />

+------------+--------------+-------------+----------------------------|


76 Značenja polja u SQLCA<br />

+------------+--------------+-------------+----------------------------|<br />

| | | | function because its |<br />

| | | | results are not dependent |<br />

| | | | on the elimination of null |<br />

| | | | values. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN3 | SQLWARN3 | CHAR(1) | Contains W if the number |<br />

| | | | of result columns is |<br />

| | | | larger than the number of |<br />

| | | | host variables. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN4 | SQLWARN4 | CHAR(1) | Contains W if a prepared |<br />

| | | | UPDATE or DELETE statement |<br />

| | | | does not include a WHERE |<br />

| | | | clause. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN5 | SQLWARN5 | CHAR(1) | Contains W if the SQL |<br />

| | | | statement was not executed |<br />

| | | | because it is not a valid |<br />

| | | | SQL statement in DB2 for |<br />

| | | | MVS/ESA. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN6 | SQLWARN6 | CHAR(1) | Contains W if the addition |<br />

| | | | of a month or year |<br />

| | | | duration to a DATE or |<br />

| | | | TIMESTAMP value results in |<br />

| | | | an invalid day (for |<br />

| | | | example, June 31). |<br />

| | | | Indicates that the value |<br />

| | | | of the day was changed to |<br />

| | | | the last day of the month |<br />

| | | | to make the result valid. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN7 | SQLWARN7 | CHAR(1) | Contains a W if one or |<br />

| | | | more nonzero digits were |<br />

| | | | eliminated from the |<br />

| | | | fractional part of a |<br />

| | | | number used as the operand |<br />

| | | | of a decimal multiply or |<br />

| | | | divide operation. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN8 | SQLWARN8 | CHAR(1) | Contains a W if a |<br />

| | | | character that could not |<br />

| | | | be converted was replaced |<br />

| | | | with a substitute |<br />

| | | | character. |<br />

+------------+--------------+-------------+----------------------------|


77<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARN9 | SQLWARN9 | CHAR(1) | Contains a W if arithmetic |<br />

| | | | exceptions were ignored |<br />

| | | | during COUNT DISTINCT |<br />

| | | | processing. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLWARNA | SQLWARNA | CHAR(1) | Contains a W if at least |<br />

| | | | one character field of the |<br />

| | | | SQLCA or the SQLDA names |<br />

| | | | or labels is invalid due |<br />

| | | | to a character conversion |<br />

| | | | error. |<br />

+------------+--------------+-------------+----------------------------|<br />

| SQLSTATE | sqlstate | CHAR(5) | Contains a return code for |<br />

| | | | the outcome of the most |<br />

| | | | recent execution of an SQL |<br />

| | | | statement (See note 5). |<br />

+----------------------------------------------------------------------|<br />

| Note: |<br />

| |<br />

| 1. With the precompiler option STDSQL(YES) in effect, SQLCODE is |<br />

| replaced by SQLCADE in SQLCA. |<br />

| |<br />

| 2. For the specific meanings of SQL return codes, see Section 2 of |<br />

| Messages and Codes. |<br />

| |<br />

| 3. In COBOL, SQLERRM includes SQLERRML and SQLERRMC. In PL/I and C, |<br />

| the varying-length string SQLERRM is equivalent to SQLERRML |<br />

| prefixed to SQLERRMC. In assembler, the storage area SQLERRM is |<br />

| equivalent to SQLERRML and SQLERRMC. See the examples for the |<br />

| various host languages in "The Included SQLCA" in topic C.1.2. |<br />

| |<br />

| 4. The use of timerons may require special handling because they |<br />

| are floating-point values in an INTEGER array. In PL/I, for |<br />

| example you could first copy the value into a BIN FIXED(31) |<br />

| based variable that coincides with a BIN FLOAT(24) variable. |<br />

| |<br />

| 5. For a description of SQLSTATE values, see Appendix C of Messages |<br />

| and Codes. |<br />

+----------------------------------------------------------------------+


Dodatak B<br />

Izgled SQLCA strukture<br />

PL/I: | C:<br />

|<br />

|<br />

DECLARE | #ifndef SQLCODE<br />

1 SQLCA, | struct sqlca<br />

2 SQLCAID CHAR(8), | {<br />

2 SQLCABC FIXED(31) BINARY, | unsigned char sqlcaid[8];<br />

2 SQLCODE FIXED(31) BINARY, | long sqlcabc;<br />

2 SQLERRM CHAR(70) VAR, | long sqlcode;<br />

2 SQLERRP CHAR(8), | short sqlerrml;<br />

2 SQLERRD(6) FIXED(31) BINARY, | unsigned char sqlerrmc[70];<br />

2 SQLWARN, | unsigned char sqlerrp[8];<br />

3 SQLWARN0 CHAR(1), | long sqlerrd[6];<br />

3 SQLWARN1 CHAR(1), | unsigned char sqlwarn[11];<br />

3 SQLWARN2 CHAR(1), | unsigned char sqlstate[5];<br />

3 SQLWARN3 CHAR(1), | };<br />

3 SQLWARN4 CHAR(1), | #define SQLCODE sqlca.sqlcode<br />

3 SQLWARN5 CHAR(1), | #define SQLWARN0 sqlca.sqlwarn[0]<br />

3 SQLWARN6 CHAR(1), | #define SQLWARN1 sqlca.sqlwarn[1]<br />

3 SQLWARN7 CHAR(1), | #define SQLWARN2 sqlca.sqlwarn[2]<br />

2 SQLEXT, | #define SQLWARN3 sqlca.sqlwarn[3]<br />

3 SQLWARN8 CHAR(1), | #define SQLWARN4 sqlca.sqlwarn[4]<br />

3 SQLWARN9 CHAR(1), | #define SQLWARN5 sqlca.sqlwarn[5]<br />

3 SQLWARNA CHAR(1), | #define SQLWARN6 sqlca.sqlwarn[6]<br />

3 SQLSTATE CHAR(5); | #define SQLWARN7 sqlca.sqlwarn[7]<br />

| #define SQLWARN8 sqlca.sqlwarn[8]<br />

| #define SQLWARN9 sqlca.sqlwarn[9]<br />

| #define SQLWARNA sqlca.sqlwarn[10]<br />

| #define SQLSTATE sqlca.sqlstate<br />

| #endif<br />

| struct sqlca sqlca;


Dodatak C<br />

Klase SQLSTATE kodova<br />

SQLSTATE values are returned to the application in the last five bytes of<br />

the SQLCA. Each five-character value is a return code that indicates the<br />

outcome of the most recently executed SQL statement.<br />

SQLSTATE values are designed so that application programs can test for<br />

specific errors or classes of errors. The first character of an<br />

SQLSTATE value indicates whether the SQL statement was executed successfully<br />

or unsuccessfully (equal to or not equal to zero, respectively).<br />

SQLSTATE values are comprised of a two-character class code value, followed<br />

by a three-character subclass code value. Class code values represent classes<br />

of successful and unsuccessful execution conditions. An application might<br />

define classes beginning with the characters ’7’ through ’9’ or ’I’ through ’Z’<br />

and subclasses for any class beginning with the characters ’I’ through ’Z’.<br />

Table 5 identifies the SQLSTATE class codes.<br />

+------------------------------------------------------------------------+<br />

| Table 5. SQLSTATE Class Codes |<br />

+------------------------------------------------------------------------|<br />

| Class | | For subcodes, |<br />

| Code | Meaning | refer to... |<br />

+--------+------------------------------------+--------------------------|<br />

| 00 | Unqualified Successful Completion | Table 6 |<br />

+--------+------------------------------------+--------------------------|<br />

| 01 | Warning | Table 7 |<br />

+--------+------------------------------------+--------------------------|<br />

| 02 | No Data | Table 8 |<br />

+--------+------------------------------------+--------------------------|<br />

| 07 | Dynamic SQL Error | Table 9 |<br />

+--------+------------------------------------+--------------------------|<br />

| 08 | Connection Exception | Table 10 |<br />

+--------+------------------------------------+--------------------------|<br />

| 09 | Triggered Action Exception | Table 11 |


82 Klase SQLSTATE kodova<br />

+--------+------------------------------------+--------------------------|<br />

| 0A | Feature Not Supported | Table 12 |<br />

+--------+------------------------------------+--------------------------|<br />

| 0F | Invalid Token | Table 13 |<br />

+--------+------------------------------------+--------------------------|<br />

| 21 | Cardinality Violation | Table 14 |<br />

+--------+------------------------------------+--------------------------|<br />

| 22 | Data Exception | Table 15 |<br />

+--------+------------------------------------+--------------------------|<br />

| 23 | Constraint Violation | Table 16 |<br />

+--------+------------------------------------+--------------------------|<br />

| 24 | Invalid Cursor State | Table 17 |<br />

+--------+------------------------------------+--------------------------|<br />

| 25 | Invalid Transaction State | Table 18 |<br />

+--------+------------------------------------+--------------------------|<br />

| 26 | Invalid SQL Statement Identifier | Table 19 |<br />

+--------+------------------------------------+--------------------------|<br />

| 2D | Invalid Transaction Termination | Table 20 |<br />

+--------+------------------------------------+--------------------------|<br />

| 34 | Invalid Cursor Name | Table 21 |<br />

+--------+------------------------------------+--------------------------|<br />

| 38 | External Function Exception | Table 22 |<br />

+--------+------------------------------------+--------------------------|<br />

| 39 | External Function Call Exception | Table 23 |<br />

+--------+------------------------------------+--------------------------|<br />

| 40 | Transaction Rollback | Table 24 |<br />

+--------+------------------------------------+--------------------------|<br />

| 42 | Syntax Error or Access Rule | Table 25 |<br />

| | Violation | |<br />

+--------+------------------------------------+--------------------------|<br />

| 44 | WITH CHECK OPTION Violation | Table 26 |<br />

+--------+------------------------------------+--------------------------|<br />

| 51 | Invalid Application State | Table 27 |<br />

+--------+------------------------------------+--------------------------|<br />

| 53 | Invalid Operand or Inconsistent | Table 28 |<br />

| | Specification | |<br />

+--------+------------------------------------+--------------------------|<br />

| 54 | SQL or Product Limit Exceeded | Table 29 |<br />

+--------+------------------------------------+--------------------------|<br />

| 55 | Object Not in Prerequisite State | Table 30 |<br />

+--------+------------------------------------+--------------------------|<br />

| 56 | Miscellaneous SQL or Product Error | Table 31 |<br />

+--------+------------------------------------+--------------------------|<br />

| 57 | Resource Not Available or Operator | Table 32 |<br />

| | Intervention | |<br />

+--------+------------------------------------+--------------------------|<br />

| 58 | System Error | Table 33 |<br />

+------------------------------------------------------------------------+


83<br />

+------------------------------------------------------------------------+<br />

| Table 6. Class Code 00: Unqualified Successful Completion |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 00000 | Execution of the SQL statement was successful and did not |<br />

| | result in any type of warning or exception condition. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 7. Class Code 01: Warning |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 01003 | Null values were eliminated from the argument of a column |<br />

| | function. |<br />

+---------+--------------------------------------------------------------|<br />

| 01004 | The value of a string was truncated when assigned to a host |<br />

| | variable. |<br />

+---------+--------------------------------------------------------------|<br />

| 01005 | Insufficient number of entries in an SQLDA. |<br />

+---------+--------------------------------------------------------------|<br />

| 0100C | One or more ad hoc result sets were returned from the |<br />

| | procedure. |<br />

+---------+--------------------------------------------------------------|<br />

| 0100E | The procedure returned too many result sets. |<br />

+---------+--------------------------------------------------------------|<br />

| 01503 | The number of result columns is larger than the number of |<br />

| | host variables provided. |<br />

+---------+--------------------------------------------------------------|<br />

| 01504 | The UPDATE or DELETE statement does not include a WHERE |<br />

| | clause. |<br />

+---------+--------------------------------------------------------------|<br />

| 01505 | The statement was not executed because it is unacceptable in |<br />

| | this environment. |<br />

+---------+--------------------------------------------------------------|<br />

| 01506 | An adjustment was made to a DATE or TIMESTAMP value to |<br />

| | correct an invalid date resulting from an arithmetic |<br />

| | operation. |<br />

+---------+--------------------------------------------------------------|<br />

| 01507 | One or more non-zero digits were eliminated from the |<br />

| | fractional part of a number used as the operand of a |


84 Klase SQLSTATE kodova<br />

| | multiply or divide operation. |<br />

+---------+--------------------------------------------------------------|<br />

| 01514 | The tablespace has been placed in the check-pending state. |<br />

+---------+--------------------------------------------------------------|<br />

| 01515 | The null value has been assigned to a host variable, because |<br />

| | the non-null value of the column is not within the range of |<br />

| | the host variable. |<br />

+---------+--------------------------------------------------------------|<br />

| 01516 | An inapplicable WITH GRANT OPTION has been ignored. |<br />

+---------+--------------------------------------------------------------|<br />

| 01517 | A character that could not be converted was replaced with a |<br />

| | substitute character. |<br />

+---------+--------------------------------------------------------------|<br />

| 01518 | The definition of the table has been changed to incomplete. |<br />

+---------+--------------------------------------------------------------|<br />

| 01519 | The null value has been assigned to a host variable, because |<br />

| | a numeric value is out of range. |<br />

+---------+--------------------------------------------------------------|<br />

| 01520 | The null value has been assigned to a host variable, because |<br />

| | the characters cannot be converted. |<br />

+---------+--------------------------------------------------------------|<br />

| 01521 | A specified server-name is undefined but is not needed until |<br />

| | the statement is executed or the alias is used. |<br />

+---------+--------------------------------------------------------------|<br />

| 01522 | The local table or view name used in the CREATE ALIAS |<br />

| | statement is undefined. |<br />

+---------+--------------------------------------------------------------|<br />

| 01523 | ALL was interpreted to exclude ALTER, INDEX, REFERENCES, and |<br />

| | TRIGGER, because these privileges cannot be granted to a |<br />

| | remote user. |<br />

+---------+--------------------------------------------------------------|<br />

| 01524 | The result of a column function does not include the null |<br />

| | values that were caused by evaluating the arithmetic |<br />

| | expression implied by the column of the view. |<br />

+---------+--------------------------------------------------------------|<br />

| 01525 | The number of INSERT values is not the same as the number of |<br />

| | columns. |<br />

+---------+--------------------------------------------------------------|<br />

| 01527 | A SET statement references a special register that does not |<br />

| | exist at the AS. |<br />

+---------+--------------------------------------------------------------|<br />

| 01528 | WHERE NOT NULL is ignored, because the index key cannot |<br />

| | contain null values. |<br />

+---------+--------------------------------------------------------------|<br />

| 01529 | As a result of the DROP INDEX, the UNIQUE constraint is no |<br />

| | longer enforced. |<br />

+---------+--------------------------------------------------------------|<br />

| 01530 | Definition change may require a corresponding change on the |


85<br />

| | read-only systems. |<br />

+---------+--------------------------------------------------------------|<br />

| 01532 | An undefined object name was detected. |<br />

+---------+--------------------------------------------------------------|<br />

| 01533 | An undefined column name was detected. |<br />

+---------+--------------------------------------------------------------|<br />

| 01537 | An SQL statement cannot be EXPLAINed, because it references |<br />

| | a remote object. |<br />

+---------+--------------------------------------------------------------|<br />

| 01538 | The table cannot be subsequently defined as a dependent, |<br />

| | because it has the maximum number of columns. |<br />

+---------+--------------------------------------------------------------|<br />

| 01539 | Connection is successful but only SBCS characters should be |<br />

| | used. |<br />

+---------+--------------------------------------------------------------|<br />

| 01540 | A limit key has been truncated to 40 bytes. |<br />

+---------+--------------------------------------------------------------|<br />

| 01542 | Authorization ID does not have the privilege to perform the |<br />

| | operation as specified. |<br />

+---------+--------------------------------------------------------------|<br />

| 01543 | A duplicate constraint has been ignored. |<br />

+---------+--------------------------------------------------------------|<br />

| 01545 | An unqualified column name has been interpreted as a |<br />

| | correlated reference. |<br />

+---------+--------------------------------------------------------------|<br />

| 01546 | A column of the explanation table is improperly defined. |<br />

+---------+--------------------------------------------------------------|<br />

| 01548 | The authorization ID does not have the privilege to perform |<br />

| | the specified operation on the identified object. |<br />

+---------+--------------------------------------------------------------|<br />

| 01551 | A table in a partitioned tablespace is not available, |<br />

| | because its partitioned index has not been created. |<br />

+---------+--------------------------------------------------------------|<br />

| 01552 | An ambiguous qualified column name was resolved to the first |<br />

| | of the duplicate names in the FROM clause. |<br />

+---------+--------------------------------------------------------------|<br />

| 01553 | Isolation level RR conflicts with a tablespace locksize of |<br />

| | page. |<br />

+---------+--------------------------------------------------------------|<br />

| 01554 | Decimal multiplication may cause overflow. |<br />

+---------+--------------------------------------------------------------|<br />

| 01558 | A distribution protocol has been violated. |<br />

+---------+--------------------------------------------------------------|<br />

| 01560 | A redundant GRANT has been ignored. |<br />

+---------+--------------------------------------------------------------|<br />

| 01561 | An update to a data capture table was not signaled to the |<br />

| | originating subsystem. |<br />

+---------+--------------------------------------------------------------|


86 Klase SQLSTATE kodova<br />

| 01566 | The index has been placed in a recover-pending state. |<br />

+---------+--------------------------------------------------------------|<br />

| 01568 | The dynamic SQL statement ends with a semicolon. |<br />

+---------+--------------------------------------------------------------|<br />

| 01569 | The statement will be executed at a DB2 system that does not |<br />

| | support character conversion. |<br />

+---------+--------------------------------------------------------------|<br />

| 01590 | Type 2 indexes do not have subpages. |<br />

+---------+--------------------------------------------------------------|<br />

| 01591 | The result of the positioned UPDATE or DELETE may depend on |<br />

| | the order of the rows. |<br />

+---------+--------------------------------------------------------------|<br />

| 01594 | Insufficient number of entries in an SQLDA for ALL |<br />

| | information (i.e. not enough descriptors to return the |<br />

| | distinct name). |<br />

+---------+--------------------------------------------------------------|<br />

| 01596 | Comparison functions were not created for a distinct type |<br />

| | based on a long string data type. |<br />

+---------+--------------------------------------------------------------|<br />

| 01597 | Specific and non-specific volume IDs are not allowed in a |<br />

| | storage group. |<br />

+---------+--------------------------------------------------------------|<br />

| 01602 | The optimization level has been reduced. |<br />

+---------+--------------------------------------------------------------|<br />

| 01608 | An unsupported value has been replaced. |<br />

+---------+--------------------------------------------------------------|<br />

| 01612 | The part clause of a LOCK TABLE statement is not valid. |<br />

+---------+--------------------------------------------------------------|<br />

| 01614 | There are fewer locators than the number of result sets. |<br />

+---------+--------------------------------------------------------------|<br />

| 01616 | The estimated CPU cost exceeds the resource limit. |<br />

+---------+--------------------------------------------------------------|<br />

| 01624 | The GBPCACHE specification is ignored because the bufferpool |<br />

| | does not allow caching. |<br />

+---------+--------------------------------------------------------------|<br />

| 01625 | The schema name appears more than once in the CURRENT PATH. |<br />

+---------+--------------------------------------------------------------|<br />

| 01628 | The user-specified access path hints are invalid. The access |<br />

| | path hints are ignored. |<br />

+---------+--------------------------------------------------------------|<br />

| 01629 | User-specified access path hints were used during access |<br />

| | path selection. |<br />

+---------+--------------------------------------------------------------|<br />

| 01635 | Statements in the same program have duplicate QUERYNOs. |<br />

+---------+--------------------------------------------------------------|<br />

| 01638 | SUBPAGES greater than one are not supported for Type 1 |<br />

| | indexes in a data sharing environment. |<br />

+---------+--------------------------------------------------------------|


87<br />

| 01Hxx | Valid warning SQLSTATEs returned by a user-defined function |<br />

| | or external procedure CALL. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 8. Class Code 02: No Data |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 02000 | One of the following exceptions occurred: |<br />

| | |<br />

| | @ The result of the SELECT INTO statement or the subselect |<br />

| | of the INSERT statement was an empty table. |<br />

| | @ The number of rows identified in the searched UPDATE or |<br />

| | DELETE statement was zero. |<br />

| | @ The position of the cursor referenced in the FETCH |<br />

| | statement was after the last row of the result table. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 9. Class Code 07: Dynamic SQL Error |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 07001 | The number of host variables is not the same as the number |<br />

| | of parameter markers. |<br />

+---------+--------------------------------------------------------------|<br />

| 07002 | The call parameter list or control block is invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 07003 | The statement identified in the EXECUTE statement is a |<br />

| | select-statement, or is not in a prepared state. |<br />

+---------+--------------------------------------------------------------|<br />

| 07005 | The statement name of the cursor identifies a prepared |<br />

| | statement that cannot be associated with a cursor. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 10. Class Code 08: Connection Exception |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 08001 | The application requester is unable to establish the |


88 Klase SQLSTATE kodova<br />

| | connection. |<br />

+---------+--------------------------------------------------------------|<br />

| 08002 | The connection already exists. |<br />

+---------+--------------------------------------------------------------|<br />

| 08003 | The connection does not exist. |<br />

+---------+--------------------------------------------------------------|<br />

| 08004 | The application server rejected establishment of the |<br />

| | connection. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 11. Class Code 09: Triggered Action Exception |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 09000 | A triggered SQL statement failed. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 12. Class Code 0A: Feature Not Supported |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 0A001 | The CONNECT statement is invalid, because the process is not |<br />

| | in the connectable state. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 13. Class Code 0F: Invalid Token |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 0F001 | The locator value does not currently represent any value. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 14. Class Code 21: Cardinality Violation |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|


89<br />

| 21000 | The result of a SELECT INTO is a result table of more than |<br />

| | one row, or the result of the subquery of a basic predicate |<br />

| | is more than one value. |<br />

+---------+--------------------------------------------------------------|<br />

| 21501 | A multiple-row INSERT into a self-referencing table is |<br />

| | invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 21502 | A multiple-row UPDATE of a primary key is invalid. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 15. Class Code 22: Data Exception |<br />

+------------------------------------------------------------------------|<br />

| SQLSTATE| |<br />

| Value | Meaning |<br />

+---------+--------------------------------------------------------------|<br />

| 22001 | Character data, right truncation occurred; for example, an |<br />

| | update or insert value is a string that is too long for the |<br />

| | column, or a datetime value cannot be assigned to a host |<br />

| | variable, because it is too small. |<br />

+---------+--------------------------------------------------------------|<br />

| 22002 | A null value, or the absence of an indicator parameter was |<br />

| | detected; for example, the null value cannot be assigned to |<br />

| | a host variable, because no indicator variable is specified. |<br />

+---------+--------------------------------------------------------------|<br />

| 22003 | A numeric value is out of range. |<br />

+---------+--------------------------------------------------------------|<br />

| 22007 | An invalid datetime format was detected; that is, an invalid |<br />

| | string representation or value was specified. |<br />

+---------+--------------------------------------------------------------|<br />

| 22008 | Datetime field overflow occurred; for example, an arithmetic |<br />

| | operation on a date or timestamp has a result that is not |<br />

| | within the valid range of dates. |<br />

+---------+--------------------------------------------------------------|<br />

| 22011 | A substring error occurred; for example, an argument of |<br />

| | SUBSTR is out of range. |<br />

+---------+--------------------------------------------------------------|<br />

| 22012 | Division by zero is invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 22018 | The character value for the CAST, DECIMAL, FLOAT, or INTEGER |<br />

| | scalar function is invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 22019 | The LIKE predicate has an invalid escape character. |<br />

+---------+--------------------------------------------------------------|<br />

| 22021 | A character is not in the coded character set. |<br />

+---------+--------------------------------------------------------------|<br />

| 22023 | A parameter or host variable value is invalid. |


90 Klase SQLSTATE kodova<br />

+---------+--------------------------------------------------------------|<br />

| 22024 | A NUL-terminated input host variable or parameter did not |<br />

| | contain a NUL. |<br />

+---------+--------------------------------------------------------------|<br />

| 22025 | The LIKE predicate string pattern contains an invalid |<br />

| | occurrence of an escape character. |<br />

+---------+--------------------------------------------------------------|<br />

| 22501 | The length control field of a variable length string is |<br />

| | negative or greater than the maximum. |<br />

+---------+--------------------------------------------------------------|<br />

| 22503 | The string representation of a name is invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 22504 | A mixed data value is invalid. |<br />

+---------+--------------------------------------------------------------|<br />

| 22505 | The local date or time length has been increased, but the |<br />

| | executing program relies on the old length. |<br />

+---------+--------------------------------------------------------------|<br />

| 22506 | A reference to a datetime special register is invalid, |<br />

| | because the TOD clock is malfunctioning or the operating |<br />

| | system timezone parameter is out of range. |<br />

+---------+--------------------------------------------------------------|<br />

| 22508 | CURRENT PACKAGESET is blank. |<br />

+---------+--------------------------------------------------------------|<br />

| 22511 | ADT length exceeds maximum column length. The value for a |<br />

| | ROWID or reference column is not valid. |<br />

+---------+--------------------------------------------------------------|<br />

| 22512 | A host variable in a predicate is invalid, because its |<br />

| | indicator variable is negative. |<br />

+---------+--------------------------------------------------------------|<br />

| 22522 | A CCSID value is not valid at all, not valid for the data |<br />

| | type or subtype, or not valid for the encoding scheme. |<br />

+---------+--------------------------------------------------------------|<br />

| 22525 | Partitioning key value is not valid. |<br />

+------------------------------------------------------------------------+<br />

+------------------------------------------------------------------------+<br />

| Table 16. Class Code 23: Constraint Violation |<br />

+------------------------------------------------------------------------|

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!