Aplikativni SQL - poincare.matf.bg.ac.rspoincare.matf.bg.ac.rs/~gordana/SQLC.pdf · Aplikativni SQL...
Transcript of Aplikativni SQL - poincare.matf.bg.ac.rspoincare.matf.bg.ac.rs/~gordana/SQLC.pdf · Aplikativni SQL...
Aplikativni SQL
Aplikativni SQL
• Interaktivni SQL
• Aplikativni SQL
– Statički SQL
– Dinamički SQL
• Druge mogućnosti ugradnje blokova za komunikaciju sa SUBP
u program.
• U slučaju sistema DB2, te mogućnosti su
– direktni pozivi DB2 funkcija (Call Level Interface – CLI)
– upotreba ODBC standarda (Open Database Connectivity) –
dinamički
– zapamćene procedure
ODBC
• ODBC: standardizovanje interfejsa korisnika i međusistema (prema
SUBP), nezavisno od SUBP kome će međusistem proslediti korisnički
zahtev.
• Nemoguće je koristiti specifičnosti pojedinog sistema (u ovom
slučaju DB2), a svi upiti upućeni sistemu DB2 preko ODBC-a
izvršavaju se dinamički.
CLI
• Direktni pozivi DB2 funkcija (CLI-sistem) su specifični za DB2 sistem i
koriste sve njegove mogućnosti (kao i aplikativni SQL), mada su
maksimalno usaglašeni sa ODBC pristupom
• CLI je alternativa aplikativnom dinamičkom SQL-u
• DB2 CLI aplikacija ne mora ni da se prekompilira ni da se povezuje
sa bazom; ona koristi standardni skup funkcija za izvršenje SQL
iskaza u vreme izvršenja programa.
• DB2 CLI aplikacija postaje ”prenosivija” u odnosu na aplikaciju u
aplikativnom SQL-u (bar kada su razne DB2 platforme u pitanju)
• osnovna prednost aplikativnog SQL-a u tome što može da koristi
statički SQL i što je u značajnoj meri standardizovan pa se može
koristiti (u manjoj ili većoj meri) i među različitim SUBP-
platformama.
CLI
• Aplikacije koriste CLI pozive funkcija u vreme izvršavanja da se
povežu sa bazama podataka, izvrše SQL iskaze i pretraže
informacije o podacima i statusu
• Primeri DB2 CLI funkcija:
• SQLConnect() – uspostavlja konekciju sa ciljnom bazom
podataka
• SQLPrepare()
• SQLExecute()
• SQLExecDirect()
• SQLRowCount()
• SQLDisconnect ()
• SQLPrimaryKeys () ...
CLI / primerSQLRETURN SQLConnect (
SQLHDBC ConnectionHandle, /* hdbc */
SQLCHAR * ServerName, /* szDSN */
SQLSMALLINT NameLength1, /* cbDSN */
SQLCHAR * UserName, /* szUID */
SQLSMALLINT NameLength2, /* cbUID */
SQLCHAR * Authentication, /* szAuthStr */
SQLSMALLINT NameLength3); /* cbAuthStr */
CLI / primer
CLI / primer
/* From the CLI sample utilcli.c */
/* ... */
/* connect to the database */
printf( "\nConnecting to %s ...\n", dbAlias ) ;
sqlrc = SQLConnect( *pHdbc, (SQLCHAR *)dbAlias, SQL_NTS, (SQLCHAR
*)user, SQL_NTS, (SQLCHAR *)pswd, SQL_NTS );
HANDLE_CHECK( SQL_HANDLE_DBC, *pHdbc, sqlrc, pHenv, pHdbc ) ;
printf( "Connected to %s.\n", dbAlias ) ;
return(0);
}
Zapamćena procedura (stored
procedure)• U slučaju da aplikacija zahteva prednosti oba mehanizma (DB2 CLI i
aplikativnog SQL-a), moguće je koristiti statički SQL unutar DB2 CLI
aplikacije kreiranjem zapamćenih procedura napisanih na statičkom
SQL-u.
• Zapamćena procedura se poziva iz DB2 CLI aplikacije i izvršava se na
serveru.
• Jednom napisanu zapamćenu proceduru može da pozove bilo koja
DB2 CLI ili ODBC aplikacija.
• Aplikacija može biti projektovana tako da se izvršava u dva dela –
jedan na klijentu a drugi na serveru.
• Zapamćene procedure imaju niz prednosti, od smanjenja mrežnog
saobraćaja pri prenosu podataka do koncepta učaurenja koji
povećava bezbednost podataka.
Zapamćena procedura (stored
procedure)• Zapamćena procedura (engl. stored procedure) je programski blok
koji se poziva iz aplikacije na klijentu a izvršava se na serveru baza
podataka.
• Piše se u odgovarajućim proširenjima SQL-a, kao što je, na primer,
Oracle PL/SQL ili C-Java/SQL u DB2, kompilira i pamti u biblioteci
odgovarajućeg SUBP.
• Deo logike aplikacije prenosi se sa klijenta na server, i povećava
funkcionalnost servera.
• Najčešći razlog za korišćenje zapamćenih procedura je intenzivna
obrada podataka iz baze podataka, koja proizvodi malu količinu
rezultujućih podataka, ili
• činjenica da je skup operacija (koje se izdvajaju u zapamćenu
proceduru) zajednički za više aplikacija.
Aplikativni (ugnježdeni) SQL
• Matični (host) jezik – C, Java, ...
• Princip dualnosti
• Slogovno / skupovni odnos: kursor
• Jednočlani rezultat: INTO linija u SELECT iskazu
• 1. prefix EXEC SQL...
• 2. EXEC SQL BEGIN DECLARE SECTION
...
EXEC SQL END DECLARE SECTION
Aplikativni (ugnježdeni) SQL
3. Obraćanju matičnoj promenljivoj u okviru SQL iskaza prethodi
dvotačka, koja razlikuje tu promenljivu od imena atributa SQL-a
EXEC SQL SELECT NASLOV, OBLAST
INTO :KNJIGA, :OBLAST
FROM K
WHERE K_SIF = :DATI_K_SIF
Indikatorska promenljiva
EXEC SQL SELECT NASLOV, OBLAST
INTO :KNJIGA, :OBLAST:O1
FROM K
WHERE K_SIF = :DATI_ K_ SIF
Aplikativni (ugnježdeni) SQL
4. Program sa izvršnim SQL iskazima komunicira sa DB2 preko
memorijskog prostora koji se zove SQL prostor za komunikaciju
(engl. SQL Communication Area, SQLCA).
• SQLCA je struktura koja se ažurira posle izvršenja svakog SQL
iskaza.
• Najčešće korišćena promenljiva SQLCA strukture je SQLCODE.
• Indikator uspešnosti: 0, <0, >0 (100)
• Uključenje u program: EXEC SQL INCLUDE SQLCA
• Pre prvog izvršnog SQL iskaza
Aplikativni (ugnježdeni) SQL
5. Provera statusa izvršavanja (SQLCODE)
Direktiva
EXEC SQL WHENEVER uslov akcija
Uslov:
• NOT FOUND (nije nađen – drugi zapis za SQLCODE = 100),
• SQLERROR (indikator greške – drugi zapis za SQLCODE < 0) ili
• SQLWARNING (indikator upozorenja – drugi zapis za SQLCODE > 0
AND SQLCODE <> 100);
Akcija:
• CONTINUE – program nastavlja sa izvršenjem ili
• GOTO obeležje – skok na deo programa u kome se nastavlja obrada,
npr. izveštavanje o uzroku nastalog uslova.
Aplikativni (ugnježdeni) SQL
Na primer,
EXEC SQL WHENEVER SQLERROR CONTINUE
SQLCA sadrži još i:
• SQLSTATE tipa CHAR[5] (slično promenljivoj SQLCODE)
(npr. prva dva karaktera ’01’ promenljive SQLSTATE predstavljaju grupu
kodova – upozorenja)
• Niz celih brojeva SQLERRD[6] koji se odnosi na razne vrste
informacija o nastaloj grešci ili rezultatu izvršavanja SQL iskaza,
• Skup CHAR(1) promenljivih SQLWARN0 – SQLWARN10 koje sadrže
informacije o uzroku upozorenja.
Aplikativni (ugnježdeni) SQL
• Neki od ovih elemenata SQLCA strukture:
• SQLERRD[3] sadrži broj vrsta obrađenih (unetih, ažuriranih ili izbrisanih)
izvršavanjem poslednjeg INSERT, UPDATE ili DELETE iskaza
• SQLERRD[5] sadrži ukupan broj izbrisanih, unetih ili ažuriranih vrsta,
direktno ili indirektno, izvršavanjem odgovarajućeg iskaza;
• SQLwarn0 sadrži ’W’ ako bar jedna od preostalih SQLwarni promenljivih
sadrži upozorenje (’W’);
• Npr. SQLWARNING u direktivi WHENEVER:
disjunkcija uslova (SQLCODE >0 AND SQLCODE <>100 )
OR SQLWARN0 = ’W’;
• SQLWARN1 sadrži ’W’ ako je pri dodeli promenljivoj matičnog jezika
odesečena vrednost kolone tipa niske znakova (CHAR(m));
• SQLWARN2 sadrži ’W’ ako je došlo do eliminacije NULL vrednosti pri
primeni agregatne funkcije.
Aplikativni (ugnježdeni) SQL: rad sa
kursorima• Deklarisanje
EXEC SQL DECLARE X CURSOR FOR
SELECT I_SIF, NAZIV, STATUS
FROM I
WHERE DRZAVA = :Y
Za čitanje:
FOR FETCH ONLY (FOR READ ONLY)
(može i u specifičnom poretku: ORDER BY)
Za ažuriranje liste kolona rezultata
FOR UPDATE OF lista-kolona
Aplikativni (ugnježdeni) SQL: rad sa
kursorima• Ne može se ažurirati ako:
• DISTINCT opciju u spoljašnjoj SELECT liniji;
• skupovnu (UNION, INTERSECT, EXCEPT) operaciju osim UNION
• ALL;
• agregatnu funkciju u spoljašnjoj SELECT liniji;
• GROUP BY ili HAVING liniju u spoljašnjem SELECT iskazu;
• ORDER BY liniju;
• podupit nad istom tabelom;
• dve ili više tabela u FROM liniji
• tabelu-pogled (u FROM liniji) koja se ne može ažurirati;
• FOR FETCH ONLY (FOR READ ONLY) opciju.
Aplikativni (ugnježdeni) SQL: rad sa
kursorima• Otvaranje i dohvatanje:
EXEC SQL OPEN X; /* otvaranje kursora */
WHILE (SQLCODE == 0) /* ima još vrsta i FETCH se uspešno izvršava */
{ EXEC SQL FETCH X INTO :I_SIF, :NAZIV, :STATUS;
/* "uzimanje" sledece vrste */
...
}
EXEC SQL CLOSE X
EXEC SQL FETCH X INTO :I_SIF, :NAZIV, :STATUS:IND;
Aplikativni (ugnježdeni) SQL: rad sa
kursorima• Ažuriranje:
EXEC SQL UPDATE I
SET STATUS = STATUS + :POVECANJE
WHERE CURRENT OF X
Aplikativni (ugnježdeni) SQL:
primerPovećanje statusa (za 10%) svim izdavačima koji su izdali knjigu sa šifrom koja
se nalazi u programskoj promenljivoj “knjiga”, može se izraziti programskom
strukturom sledećeg oblika:
#include <stdio.h>
#include <stdlib.h>
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
char knjiga[5];
char i[6];
char naziv[20];
short status;
char drzava[20];
short n_ind, s_ind, d_ind;
EXEC SQL END DECLARE SECTION;
Aplikativni (ugnježdeni) SQL:
primerVoid greska(char *poruka)
{...
printf("SQL greska, SQLCODE = %i, %s\n ", SQLCODE, poruka);
EXEC SQL ROLLBACK;
exit(0);
}
Aplikativni (ugnježdeni) SQL:
primer{EXEC SQL CONNECT to izdavastvo;
if (SQLCODE <> 0) greska(" pri otvaranju konekcije");
EXEC SQL DECLARE Z CURSOR FOR
SELECT I_SIF, NAZIV, STATUS, DRZAVA
FROM I
WHERE EXISTS
(SELECT *
FROM KI
WHERE KI.I_SIF = I.I_SIF AND KI.K_SIF = :knjiga)
FOR UPDATE OF STATUS
EXEC SQL WHENEVER NOT FOUND CONTINUE;
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL WHENEVER SQLWARNING CONTINUE;
...
Aplikativni (ugnježdeni) SQL:
primerEXEC SQL OPEN Z;
if (SQLCODE <> 0) greska(" pri otvaranju kursora Z");
EXEC SQL FETCH Z INTO :i, :naziv:n_ind, :status:s_ind, :drzava:d_ind;
if (SQLCODE == 100)
greska(" nema izdavaca koji su izdali datu knjigu");
if (SQLCODE <>0)
greska(" pri prvom uzimanju vrste o trazenom izdavacu");
while(SQLCODE <> 100)
{
printf("naziv izdavaca je %s", naziv);
EXEC SQL UPDATE I
SET STATUS = STATUS * 1.1
WHERE CURRENT OF Z;
Aplikativni (ugnježdeni) SQL:
primerIf ((SQLCODE <> 0))
greska(" pri azuriranju tekuceg izdavaca");
EXEC SQL FETCH Z INTO :i, :naziv:n_ind, :status:s_ind, :drzava:d_ind;
if ((SQLCODE <> 0) && (SQLCODE <> 100))
greska(" pri uzimanju (FETCH) sledeceg izdavaca");
}
EXEC SQL CLOSE Z;
if (SQLCODE <> 0) greska(" pri zatvaranju kursora Z");
EXEC SQL COMMIT;
if (SQLCODE <> 0) greska(" pri operaciji COMMIT");
EXEC SQL CONNECT RESET;
if (SQLCODE <> 0) greska(" pri zatvaranju konekcije");
}
Dinamički SQL
• U statičkom SQL-u iskaz je poznat u vreme pisanja (prekompilacije)
programa
• Statički SQL iskaz u pretkompilaciji se zamenjuje fiksiranim
(poznatim) CLI pozivom
• U dinamičkom SQL-u iskaz je poznat tek u vreme izvršavanja
programa
• Iskaz je vrednost matične promenljive tipa niske znakova
• Vredost matične promenljive (pa i SQL iskaza) može da se menja u
toku izvršavanja programa
• Nad dinamičkim SQL iskazom potrebno je primeniti statički
PREPARE iskaz i zatim statički EXECUTE iskaz
• EXEC SQL PREPARE S1 FROM :V1
• EXEC SQL EXECUTE S1
Dinamički SQL
• Mogu da se pripreme i izvrše izvršni iskazi, na primer:
• ALTER, COMMIT, CREATE, DELETE, DROP, INSERT, ROLLBACK,
SELECT, SET, UPDATE,...
• statički iskaz EXECUTE IMMEDIATE
• Na primer, vrednost matične promenljive V1 jeste niska
znakova “DELETE FROM KI WHERE K_SIF = ’k1’ ”,
• iskaz
• EXEC SQL EXECUTE IMMEDIATE :V1
Dinamički SQL
• Matične promenljive:
• Primer: Neka je vrednost matične promenljive V1 niska
znakova “INSERT INTO K VALUES (?, ?, ?)”
• Posle izvršenja iskaza
• EXEC SQL PREPARE K_INSERT FROM :V1
• Izvršava se i iskaz
• EXEC SQL EXECUTE K_INSERT USING :KSIFRA, :KNASLOV,
:KOBLAST
Dinamički SQL
• Ne mogu dinamički da se izvrše:
CLOSE
DECLARE
EXECUTE
EXECUTE IMMEDIATE
FETCH
OPEN
PREPARE
WHENEVER
Dinamički SQL
• Dinamički pripremljen SELECT iskaz može da se izvrši
korišćenjem kursora:
• 1. priprema iskaza
• 2. deklarisanje kursora nad imenom iskaza
• 3. otvaranje kursora
• 4. uzimanje vrsta iz rezultujuće tabele
• 5. zatvaranje kursora
Dinamički SQL: primer
• Neka program pretražuje šifre knjiga i šifre izdavača iz tabele
KI, dinamičkim izvršavanjem SELECT iskaza oblika
SELECT K_SIF, I_SIF
FROM KI
WHERE ...
(iskaz se čita sa terminala, a korisnik zadaje uslov u WHERE liniji)
Dinamički SQL: primer
EXEC SQL PREPARE ISKAZ FROM :KI_NISKA;
...
EXEC SQL DECLARE C1 CURSOR FOR ISKAZ;
...
EXEC SQL OPEN C1;
WHILE ...
{ ...
EXEC SQL FETCH C1 INTO :K BR, :I BR;
...
}
...
EXEC SQL CLOSE C1;
Dinamički SQL
Dinamički SQL nudi potpunu fleksibilnost
programiranja.