240 likes | 398 Views
Programovanie DB aplikácií. Embedded SQL Z. Ondrejčíková. Čo potrebujeme. Interaktívne načítanie parametrov SQL príkazu zo vstupu Testovanie dat Spracovávanie výstupu SELECTu procedurálny alebo objektový jazyk. Príklad- Školský informačný systém. Student (ids, meno, rocnik, obor)
E N D
Programovanie DB aplikácií Embedded SQL Z. Ondrejčíková
Čo potrebujeme • Interaktívne načítanie parametrov SQL príkazu zo vstupu • Testovanie dat • Spracovávanie výstupu SELECTu • procedurálny alebo objektový jazyk
Príklad- Školský informačný systém Student (ids, meno, rocnik, obor) Ucitel (idu, meno, katedra) Predmet (idp, nazov, idu) Zapisany (ids, idp)
Príklad - SIS • Vlož do tabuľky Predmet predmet zadaný premennými: predmet_, idp_, idu_ • V klasickom SQL nemôžeme vkladať vopred neznáme hodnoty • Riešením je embedded SQL
Syntax Pro*C/C++ • Hostiteľským jazykom je C/C++ • Každý SQL dotaz začína EXEC SQL a končí bodkočiarkou (;) • EXEC SQL funguje ako direktiva preprocesoru • Hostiteľské premenné sa môžu používať aj vnútri SQL dotazu – píše sa pred nich dvojbodka
Pripojenie sa k databáze • EXEC SQL CONNECT meno/heslo • EXEC SQL CONNECT meno IDENTIFIED BY heslo
Odpojenie • S uložením zmien: EXEC SQL COMMIT WORK RELEASE • Bez uloženia zmien : EXEC SQL ROLLBACK WORK RELEASE
Include • Sqlca.h – sql communicative area (informácie o prevedení SQL dotazov; chyby, varovania...) • EXEC SQL INCLUDE sqlca; • #include<sqlca.h>
Deklaratívne nič nevykonávajú Môžu sa v programe nachádzať všade tam, kde sa môžu nachádzať deklarácie v C Musia predchádzať výkonným Výkonné priamo pracujú s DB Vždy po ich prevedení by sa mala previesť kontrola, či prebehli bez chýb Deklaratívne vs. výkonné SQLdotazy
Reakcia na chyby • EXEC SQL WHENEVER podmienka akcia • podmienka = NOT FOUND | SQLERROR | SQLWARNING • akcia = do meno_funkcie() | break | continue | goto label
Reakcia na chyby • EXEC SQL WHENEVER popisuje, ako sa má reagovať na nejaký druh chyby • Platí na všetky príkazy, ktoré sú pozične za ním, až do nasledujúceho „whenever“ s tou istou podmienkou
Príklad 1 • Vložiť do tabuľky Predmet predmet určený premennými predmet_, idp_, idUcitel_ #include <sqlca.h> #include <stdio.h>
Príklad 1 int main () { /* deklaracia premennych */ EXEC SQL BEGIN DECLARE SECTION; int idp_ = 1; int idUcitel_ = 11; char predmet_ [20] = “Matematika”; EXEC SQL END DECLARE SECTION; /* osetrenie chyb */ EXEC SQL WHENEVER SQLERROR do printf (“Chyba”); EXEC SQL CONNECT “scott/tiger”; if (sqlca.sqlcode == 0) { EXEC SQL INSERT INTO Predmet (idp, nazov, idu) VALUES (:idp_, :predmet_, :idUcitel_); } EXEC SQL COMMIT WORK RELEASE; }
Poznámky • Jednoriadkové komentáre musia byť uvedené /*...*/, nesmú sa používať komentáre //... • sqlca je štruktura obsahujúca niekoľko komponent, ktoré nám pomáhajú zistiť ako prebehol SQL dotaz • Všetky komponenty a ich popis nájdete na:http://rfhs8012.fh-regensburg.de/~oracle/proc/ch12.html#ERR
Poznámky • sqlca.sqlcode má hodnotu nula, ak posledný sql dotaz prebehol správne • Hostiteľské premenné sa môžu volať aj rovnakým menom ako tabuľky, názvy atributov tabuliek a iné identifikátory SQL dotazov (sú uvedené s : na zaciatku) • Konvencia – premenné označujúce data ekvivalentné atributom sa zvyknú nazývať rovnako ako atribut s „_“ na konci
Príklad 2 • Zisti meno študenta s identifikačným číslom 1. EXEC SQL BEGIN DECLARE SECTION; char meno[20]; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT meno INTO :meno; FROM Student WHERE Student.ids=1;
Použitie premenných v embedded SQL • Ako vstupné premenné pre dotaz SQL: INSERT, UPDATE, DELETE • Ako výstup dotazu SQL (kam sa má výstup uložiť) : SELECT
Práca s poľami • Doteraz sme pracovali vždy s jedným záznamom tabuľky (vkládanie jedného záznamu, vyberanie jedného záznamu) • Väčšinou viac záznamov • Zjednodušenie práce : polia
Príklad 3 • Vlož do tabuľky Zapisany hodnoty z polí idp_, ids_. Tzn. V poli idp_ máme uložené čísla predmetov a v poli ids_ čísla študentov v odpovedajúcom si poradí. /* polia uz predpokladame naplnene */ EXEC SQL INSERT INTO Zapisany (idp, ids) VALUES (:idp_, :ids_); • Tento príkaz urobí to isté ako nasledujúci: /* riadiaca premenna i musi byt deklarovana v ramci declare section */ for (i=0; i< MAX; i++) { EXEC SQL INSERT INTO Zapisany (idp, ids) VALUES (:idp_[i], :ids_[i]); }
SELECT INTO pole • Väčšinou je výsledkom SELECTu viac ako jeden riadok • Príklad : EXEC SQL BEGIN DECLARE SECTION; int ids[20]; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT ids INTO :ids FROM Student; • Vloží do poľa ids ident. čísla všetkých študentov
Problém • Predchádzajúci príklad bude fungovať iba v prípade, že výsledkom SELECTu nebude viac ako 20 riadkov • Pre viac ako 20 riadkov sa do poľa ids dostane iba prvých 20 riadkov • Riešenie : SELECT zanoríme do cyklu (ak ešte nie sú spracované všetky riadky, pokračuj) • Problém : Každý priechod cyklom sa do poľa dostane vždy tých istých prvých 20 riadkov
Kurzory • Sú to akési ukazatele aktuálneho riadku • Správne riešenie predchádzajúceho príkladu: EXEC SQL DECLARE c CURSOR FOR SELECT ids FROM Student; EXEC SQL OPEN c; EXEC SQL WHENEVER NOT FOUND do break; for (;;) { EXEC SQL FETCH c INTO :ids; /* ... spracovanie ids... */ }
Poznámky • DECLARE CURSOR je čisto deklaratívny príkaz, nič nevykonáva, označuje daný príkaz (v našom prípade SELECT) a pomenováva ho • Až OPEN CURSOR je výkonným príkazom; pri jeho zavolaní sa vykoná príkaz definovaný kurzorom c • Príkaz WHENEVER spôsobí opustenie cyklu vo chvíli, kedy sme spracovali všetky riadky a nie je nájdený žiaden ďalší • Príkaz FETCH postupne do premennej ids načíta toľko riadkov z výstupu SELECTu, koľko je možné (v našom prípade 20) a normálne nasleduje spracovanie týchto riadkov
Pokračovanie Nadvädzujú referáty • Dynamic SQL • Transakčné spracovanie