aplikativni sql - poincare.matf.bg.ac.rspoincare.matf.bg.ac.rs/~gordana/pred4-sqlc.pdf ·...

42
APLIKATIVNI SQL Gordana Pavlović-Lažetić Matematički fakultet, Beograd šk. 2018/19.

Upload: others

Post on 31-Dec-2019

49 views

Category:

Documents


0 download

TRANSCRIPT

APLIKATIVNI SQLGordana Pavlović-Lažetić

Matematički fakultet, Beograd

šk. 2018/19.

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

Dinamički SQL

Dinamički SQL nudi potpunu fleksibilnost

programiranja.

25/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