aplikativni sql - poincare.matf.bg.ac.rspoincare.matf.bg.ac.rs/~gordana/pred4-sqlc.pdf ·...
TRANSCRIPT
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
2/42
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
3/42
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
4/42
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
5/42
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 zaSQLCODE > 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.
6/42
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.
7/42
Aplikativni (ugnježdeni) SQL
• Neki od ovih elemenata SQLCA strukture:
• SQLERRD[3] sadrži broj vrsta obrađenih (unetih, ažuriranih iliizbrisanih) 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 SQLWARNipromenljivih 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 jezikaodesečena vrednost kolone tipa niske znakova (CHAR(m));
• SQLWARN2 sadrži ’W’ ako je došlo do eliminacije NULL vrednosti pri
primeni agregatne funkcije.
8/42
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
9/42
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.
10/42
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;
11/42
Aplikativni (ugnježdeni) SQL: rad sa
kursorima• Ažuriranje:
EXEC SQL UPDATE I
SET STATUS = STATUS + :POVECANJE
WHERE CURRENT OF X
12/42
Aplikativni (ugnježdeni) SQL: primer
Poveć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;
13/42
Aplikativni (ugnježdeni) SQL: primer
Void greska(char *poruka)
{...
printf("SQL greska, SQLCODE = %i, %s\n ", SQLCODE,
poruka);
EXEC SQL ROLLBACK;
exit(0);
}
14/42
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;
...
15/42
Aplikativni (ugnježdeni) SQL: primer
EXEC 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;
16/42
Aplikativni (ugnježdeni) SQL: primer
If ((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");
}
17/42
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
18/42
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
19/42
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
20/42
Dinamički SQL
• Ne mogu dinamički da se izvrše:
CLOSE
DECLARE
EXECUTE
EXECUTE IMMEDIATE
FETCH
OPEN
PREPARE
WHENEVER
21/42
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
22/42
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)
23/42
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;
24/42
CLI
• DB2 CLI je IBM-ov C i C++ API za pristup bazi podataka koji
koristi pozive funkcija za prosleđivanje dinamičkih SQL naredbi
kao argumenata funkcija
• Dakle, CLI je alternativa aplikativnom dinamičkom SQL-u
• DB2 CLI program ne zahteva pretprocesiranje niti vezivanje za
bazu podataka, već koristi standardni skup funkcija za
izvršavanje SQL naredbi i odgovarajućih servisa u vreme
izvršavanja
• Ovo je je značajno jer su pretprocesori, tradicionalno, specifični
za neki konkretan proizvod koji radi nad bazom, što efektivno
vezuje razvijenu aplikaciju za taj proizvod
26/42
CLI
• Zato DB2 CLI aplikacija postaje prenosivija u odnosu na
aplikaciju u aplikativnom SQL-u (bar kada su razne DB2
platforme u pitanju)
• Aplikacija se povezuje sa odgovarajućom bazom podataka u
vreme izvršavanja programa
• Sa druge strane, 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
• DB2 CLI ne koristi globalne strukture SQLCA i SQLDA, već sam alocira i kontroliše potrebne strukture podataka
27/42
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:• Povezivanje:
• SQLConnect() – uspostavlja konekciju sa ciljnom bazom podataka• SQLDisconnect();• Obrada:• SQLPrepare()• SQLExecute()• SQLExecDirect()• Čitanje iz rezultata upita:
• SQLFetch() • SQLBindCol()• SQLBindParameter()
28/42
CLI - primer
• Funkcija kojom se utvrđuje da li je više knjiga izdato u
2000. godini ili u 2010. godini.
29/42
#include "sqlcli.h"
void vise_knjiga(){
int br_2000=0, br_2010=0;
SQLHENV mojeOkr;
SQLHDBC mojaKon;
SQLHSTMT naredba;
SQLSMALLINT godina, godinaInfo;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, mojeOkr);
SQLAllocHandle(SQL_HANDLE_DBC, mojeOkr, &mojaKon);
SQLAllocHandle(SQL_HANDLE_STMT, mojaKon, &naredba);
SQLPrepare(naredba,"SELECT god_izdavanja FROM Knjiga", SQL_NTS);
SQLExecute(naredba);
SQLBindCol(naredba, 1, SQL_SMALLINT, &godina, sizeof(godina), &godinaInfo);
while(SQLFetch(naredba) != SQL_NO_DATA) {
if (godina == 2000)
br_2000++;
else if (godina == 2010)
br_2010++;
}
if (br_2000 > br_2010)
printf("Vise knjiga je izdato u 2000. godini\n");
else
printf("Vise knjiga je izdato u 2010. godini\n");
}
30/42
ODBC
• ODBC: standardizovanje interfejsa korisnika i međusistema(prema SUBP), nezavisno od SUBP kome će međusistemproslediti korisnički zahtev.
• Aplikacija se direktno linkuje sa jednom bibliotekom menadžera drajvera umesto sa bibliotekom za svaki SUBP
• Menadžer drajvera posreduje između poziva funkcija u vremeizvršavanja aplikacije i obezbeđuje da su oni usmereni kaodgovarajućem ODBC drajveru za odgovarajući SUBP
• S obzirom na to da su ODBC menadžeru drajvera poznate samo ODBC funkcije, nemoguće je koristiti specifične funkcije pojedinog sistema (u ovom slučaju DB2)
• Svi upiti upućeni sistemu DB2 preko ODBC-a izvršavaju sedinamički.
31/42
JDBC
• JDBC API (koji je sličan ODBC API-ju) obezbeđuje standardan način za pristup bazi podataka iz Java koda.
• Java kod prosleđuje SQL naredbe kao argumente funkcija DB2 JDBC drajveru i drajver ih dalje obrađuje
• Naredba u Javi kojom se pravi konekcija je:
• Connection mojaKonekcija = DriverManager.getConnection(<URL>,
• <username>,<password>);
• Za DB2, URL je "jdbc:db2://<host_name>/<database_name>„
• Pravljenje naredbi – metode:
• createStatement() – objekat tipa Statement - samo „pokazivač“ na naredbu
• prepareStatement(Q) – prepared statement
32/42
JDBC – primeri funkcija
• Izvršavanje naredbi:
• executeQuery(Q) – primenjuje se na objekte tipa Statement
• executeQuery() – primenjuje se na PreparedStatement
• executeUpdate(U) - primenjuje se na objekte tipa Statement
• executeUpdate() - primenjuje se na PreparedStatement
• Na primer
Statement upit1 = mojaKonekcija.createStatement();
ResultSet godine_i_izdavaci = upit1.executeQuery(
"SELECT god_izdavanja, izdavac FROM Knjiga");
PreparedStatement upit2 = mojaKonekcija.prepareStatement(
"SELECT god_izdavanja, izdavac FROM Knjiga");
ResultSet godine_i_izdavaci = upit2.executeQuery();
33/42
JDBC – primeri funkcija
Statement dodaj1 = mojaKonekcija.createStatement();
int brRedova = dodaj1.executeUpdate("INSERT INTO Knjiga
VALUES(111,'Na Drini cuprija','Zavod za udzbenike',2009)");
System.out.println("Broj dodatih redova: " + brRedova);
• ili
PreparedStatement dodaj2 = mojaKonekcija.prepareStatement(
"INSERT INTO Knjiga VALUES(111,'Na Drini cuprija', " +
" 'Zavod za udzbenike',2009)");
int brRedova = dodaj2.executeUpdate();
System.out.println("Broj dodatih redova: " + brRedova);
34/42
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.
35/42
Zapamćena procedura (stored procedure)
• Zapamćena procedura (engl. stored procedure) je programski blokkoji se poziva iz aplikacije na klijentu a izvršava se na serveru bazapodataka
• Piše se u jeziku opšte namene ili u odgovarajućim proširenjima SQL-a, kao što je, na primer, C-Java/SQL u DB2, kompilira i pamti u biblioteci odgovarajućeg SUBP
• Deo logike aplikacije prenosi se sa klijenta na server, i povećavafunkcionalnost 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ćenuproceduru) zajednički za više aplikacija.
• SQL/PSM standard (engl. Persistant Stored Modules) – proširenje SQL-a konstruktima proceduralnih jezika
36/42
Zapamćena procedura (stored procedure)
• Zapamćene procedure ostvaruju mnoge prednosti:
• 1. koriste prednosti moćnih servera;
• 2. donose poboljšanja performansi statičkom SQL-u;
• 3. smanjuju mrežni saobraćaj;
• 4. poboljšavaju integritet podataka dopuštanjem raznim aplikacijamada pristupe istom programskom kodu.
37/42
Zapamćena procedura i funkcija -
definisanje
CREATE PROCEDURE <naziv>(<parametri>)
<lokalne_deklaracije>
<telo_procedure>;
CREATE FUNCTION <naziv>(<parametri>) RETURNS <tip>
<lokalne_deklaracije>
<telo_funkcije>;
38/42
Zapamćena procedura - primer
CREATE PROCEDURE Zameni( IN stari_izdavac char(30),
IN novi_izdavac char(30))
UPDATE Knjiga
SET izdavac = novi_izdavac
WHERE izdavac = stari_izdavac;
39/42
Neke naredbe u PSM• naredba poziva
CALL <naziv_procedure>(<lista argumenata>);
Npr.
EXEC SQL CALL Zameni('Prosveta','Nova prosveta');
ili
EXEC SQL CALL Zameni('Prosveta',:x);
• naredba vraćanja vrednosti:
RETURN <izraz>;
• deklaracija lokalnih promenljivih
DECLARE <naziv> <tip>;
• naredbe dodele
SET <promenljiva> = <izraz>;
• Grupna naredba BEGIN ... END
• Uslovna naredba IF – ENDIF (ELSE, ELSEIF)
• Petlja
LOOP
<lista_naredbi>
END LOOP;...
40/42
Funkcija u PSM - primer
• Funkcija uzima kao argumente naziv izdavača i i godinu g i vraća TRUE ako i samo ako je izdavač i izdao bar jednu knjigu u godini g ili ako u tokute godine nije izdata nijedna knjiga.
CREATE FUNCTION IzdaoUGod(i CHAR(30), g SMALLINT) RETURNS BOOLEAN
IF NOT EXISTS(
SELECT * FROM Knjiga WHERE god_izdavanja = g)
THEN RETURN TRUE;
ELSEIF 1 <=
(SELECT COUNT(*) FROM Knjiga WHERE god_izdavanja = g AND izdavac = i)
THEN RETURN TRUE;
ELSE RETURN FALSE;
END IF;
41/42
Procedura u PSM - primerCREATE PROCEDURE Obrada_knjige(IN sifra_knjige INTEGER)DECLARE naziv_knjige CHAR(50);BEGIN
SELECT naziv INTO naziv_knjigeFROM KnjigaWHERE k_sifra = sifra_knjige;
.../* ovde ide dalja obrada naziva knjige */ ...END
CREATE PROCEDURE Obrada_knjige(IN sifra_knjige INTEGER)DECLARE naziv_knjige CHAR(50);BEGIN
SET naziv = (SELECT naziv FROM KnjigaWHERE k_sifra = sifra_knjige);
.../* ovde ide dalja obrada naziva knjige*/ ...END
42/42