Sadrzaj - Alas
Sadrzaj - Alas
Sadrzaj - Alas
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 />
+------------------------------------------------------------------------|