Title: Vnoren
1Vnorené SQL(embedded SQL)Dotazovacà jazyky I
- Jan Sequens
- MFF UK, ak. rok 2009/2010
2Použité zdroje
- Chapter 6 Embedded SQL, ProC/C Precompiler
Programmers guide, Release 9.2, Oracle
Corporation - http//download.oracle.com/docs/cd/B10501_01/appde
v.920/a97269/pc_06sql.htm - Chapter 13 Application Programming I Embedded
SQL, A Guide to DB2, 4/e, C J Date, Colin J White - Embedded SQL Introduction to ProC, Ankur Jain
and Jeff Ullman - http//infolab.stanford.edu/ullman/fcdb/oracle/or
-proc.html - Embedded SQL v C/C, Katerina Opocenská
- http//www.ms.mff.cuni.cz/kopecky/vyuka/oracle2/o
ra2_opoc.pdf
3Obsah této prezentace
- Co je vnorenĂ© SQL a jak se pouĹľĂvá
- Hostitelské a indikátorové promenné
- PrĂkazy INSERT, UPDATE, DELETE, SELECT
- Kurzory
- Ošetrenà chyb
4Co a k cemu je vnorené SQL?
- Zpusob pouĹľitĂ SQL v programovacĂch jazycĂch
- SQL vepsané ve zdrojovém kódu jiného
programovacĂho jazyka - Všechny prĂkazy interaktivnĂho SQL jdou pouĹľĂt ve
vnoreném SQL
5Co a k cemu je vnorené SQL?
- Zpusob pouĹľitĂ SQL v programovacĂch jazycĂch
- SQL vepsané ve zdrojovém kódu jiného
programovacĂho jazyka - Všechny prĂkazy interaktivnĂho SQL jdou pouĹľĂt ve
vnoreném SQL (nikoliv naopak)
6Jak vnorenĂ© SQL pouĹľĂváme?
- Náš databázovĂ˝ systĂ©m musĂ mĂt podporu vnorenĂ©ho
SQL v našem programovacĂm jazyce
7Jak vnorenĂ© SQL pouĹľĂváme?
IBM DB2
Oracle
Microsoft SQL Server
MySQL
8Jak vnorenĂ© SQL pouĹľĂváme?
IBM DB2
C/C, COBOL, FORTRAN, REXX
Oracle
Microsoft SQL Server
MySQL
9Jak vnorenĂ© SQL pouĹľĂváme?
IBM DB2
C/C, COBOL, FORTRAN, REXX
Oracle
Ada, C/C, COBOL, Fortran, Pascal, PL/1
Microsoft SQL Server
MySQL
10Jak vnorenĂ© SQL pouĹľĂváme?
IBM DB2
C/C, COBOL, FORTRAN, REXX
Oracle
Ada, C/C, COBOL, Fortran, Pascal, PL/1
Microsoft SQL Server
Od verze 2008 ukoncena oficiálnà podpora
MySQL
11Jak vnorenĂ© SQL pouĹľĂváme?
IBM DB2
C/C, COBOL, FORTRAN, REXX
Oracle
Ada, C/C, COBOL, Fortran, Pascal, PL/1
Microsoft SQL Server
Od verze 2008 ukoncena oficiálnà podpora
MySQL
Nepodporováno
12Jak vnorenĂ© SQL pouĹľĂváme?
- PrĂklad vnorenĂ©ho SQL (Oracle a C)
- include ltstdio.hgt
- include ltsqlca.hgt
- int main(void)
-
- EXEC SQL INSERT INTO osoby (prijmeni) VALUES
(Sequens) - return 0
-
13Jak vnorenĂ© SQL pouĹľĂváme?
- VloĹľĂme hlavickovĂ˝ soubor struktury SQL
Communication Area (SQLCA) - PrĂkazy vnorenĂ©ho SQL zacĂnáme direktivou EXEC
SQL a ukoncujeme strednĂkem
14Jak vnorenĂ© SQL pouĹľĂváme?
- Oracle prostredà pro SQL vnorené v C/C se
nazĂ˝vá ProC/C - ZdrojovĂ© soubory s prĂponou .pc
- Prekompilátor ProC/C preložà .pc na cistý
C/C kĂłd - NahrazenĂ konstrukcĂ vnorenĂ©ho SQL volánĂmi
standardnà run-time knihovny - C/C kód je standardne zkompilován
15Hostitelské promenné
- Predávánà dat mezi SQL a C/C
- Ve vnoreném SQL oznacujeme dvojteckou
- VstupnĂ
- EXEC SQL INSERT INTO osoby (prijmeni) VALUES
(prijmeni_osoby) - VĂ˝stupnĂ
- EXEC SQL SELECT prijmeni INTO prijmeni_osoby
FROM osoby
16Indikátorové promenné
- Motivace Co uložit do promenné, když SELECT
vrátà NULL? - Rešenà Použijeme druhou, sprátelenou
promennou, která bude indikovat, jak a zda je
puvodnà promenná naplnena - Indikátorová promenná se zapisuje bezprostredne
za puvodnà promennou, oddelená dvojteckou
17IndikátorovĂ© promennĂ© u vĂ˝stupnĂch promennĂ˝ch
Indikátorová promenná Hostitelská promenná
-2 OrĂznutá hodnota z databáze, hodnota se do hostitelskĂ© promennĂ© nevejde a jejĂ velikost nemuĹľe bĂ˝t urcena.
-1 Nedefinovaná hodnota, v databázi byla NULL.
0 Hodnota z databáze, nenà to NULL.
gt0 OrĂznutá hodnota z databáze, hodnota se do hostitelskĂ© promennĂ© nevejde. Indikátorová promenná obsahuje velikost hodnoty v databázi.
18IndikátorovĂ© promennĂ© u vĂ˝stupnĂch promennĂ˝ch -
prĂklad
- EXEC SQL SELECT pocet_deti INTO pocetind_pocet
FROM osoby WHERE prijmeni Sequens - if (ind_pocet -1) / NULL v databázi /
- pocet 0
19IndikátorovĂ© promennĂ© u vstupnĂch promennĂ˝ch
- OvlivnĂ, co se zapĂše do databáze v prĂkazech
INSERT nebo UPDATE
Indikátorová promenná Zápis do databáze
-1 ZapÚe se NULL (hodnota hostitelské promenné se bude ignorovat).
gt 0 ZapÚe se hodnota hostitelské promenné.
20PrĂkaz INSERT
- StejnĂ© pouĹľitĂ jako pri interaktivnĂm SQL
- Skutecný zápis proveden až po zapsánà zmen
prĂkazem COMMIT - EXEC SQL INSERT INTO osoby (jmeno, prijmeni)
- VALUES (jmeno_osoby, prijmeni_osoby)
21PrĂkaz UPDATE
- StejnĂ© pouĹľitĂ jako pri interaktivnĂm SQL
- Skutecný zápis proveden až po zapsánà zmen
prĂkazem COMMIT - EXEC SQL UPDATE osoby
- SET jmeno jmeno_osoby
- WHERE prijmeni prijmeni_osoby
22PrĂkaz DELETE
- StejnĂ© pouĹľitĂ jako pri interaktivnĂm SQL
- Skutecné smazánà provedeno až po zapsánà zmen
prĂkazem COMMIT - EXEC SQL DELETE FROM osoby
- WHERE prijmeni prijmeni_osoby
23PrĂkaz SELECT
- V zásade stejnĂ© pouĹľitĂ jako u interaktivnĂho SQL
- Je treba vyrešit, kam a jak uloĹľĂme to, co SELECT
vrátĂ
24PrĂkaz SELECT
- VĂme-li, Ĺľe náš SELECT vrátĂ nejvýše jeden rádek,
je situace jednoduchá
25PrĂkaz SELECT
- VĂme-li, Ĺľe náš SELECT vrátĂ nejvýše jeden rádek,
je situace jednoduchá - EXEC SQL SELECT jmeno, prijmeni
- INTO jmeno_osoby, prijmeni_osoby
- FROM osoby
26PrĂkaz SELECT
- VĂme-li, Ĺľe náš SELECT vrátĂ nejvýše jeden rádek,
je situace jednoduchá - EXEC SQL SELECT jmeno, prijmeni
- INTO jmeno_osoby, prijmeni_osoby
- FROM osoby
- VracĂ-li SELECT vĂce neĹľ jeden rádek, je treba
pouĹľĂt ke zpracovánĂ vĂ˝sledku tzv. kurzor
27Kurzor
- Nástroj pro práci s mnoĹľinou rádku, kterou vracĂ
prĂkaz SELECT - UdrĹľuje ukazatel na aktuálnĂ zpracovávanĂ˝ rádek
28Princip práce s kurzorem
- DECLARE CURSOR
- Urcenà SQL dotazu, se kterým bude kurzor pracovat
- OPEN
- Provedenà SQL dotazu, se kterým kurzor pracuje
- FETCH
- Nactenà jednoho rádku z výsledku dotazu
- CLOSE
- Ukoncenà práce s kurzorem
29DECLARE CURSOR
- Pojmenovánà kurzoru
- Asiociace s dotazem
- EXEC SQL DECLARE osoby_kurzor CURSOR FOR
- SELECT jmeno, prijmeni
- FROM osoby
- WHERE pocet_deti gt minimalni_plodnost
30DECLARE CURSOR
- Pojmenovánà kurzoru
- Asiociace s dotazem
- EXEC SQL DECLARE osoby_kurzor CURSOR FOR
- SELECT jmeno, prijmeni
- FROM osoby
- WHERE pocet_deti gt minimalni_plodnost
- Nezahrnujeme klauzuli INTO
31OPEN
- Navázánà hostitelských promenných
- Vykonánà dotazu
- EXEC SQL OPEN osoby_kurzor
32FETCH
- Nactenà rádku z výsledku
- Posunutà ukazatele na dalšà rádek
- EXEC SQL FETCH osoby_kurzor
- INTO jmeno_osoby, prijmeni_osoby
33FETCH
- Nactenà rádku z výsledku
- Posunutà ukazatele na dalšà rádek
- EXEC SQL FETCH osoby_kurzor
- INTO jmeno_osoby, prijmeni_osoby
- Klauzule INTO se pouĹľije zde, nikoliv v deklaraci
kurzoru - Kurzor musà být deklarován a otevren.
34CLOSE
- Uzavre kurzor, uvolnĂ zdroje.
- Posunutà ukazatele na dalšà rádek
- EXEC SQL CLOSE osoby_kurzor
35Ošetrenà chyb
- Ke smysluplnĂ©mu prĂkladu pouĹľitĂ kurzoru nám
chybà zpusob, jak ošetrit chyby - Prvnà možnost je testovat po každém vnoreném SQL
prĂkazu, zda-li nedošlo k chybe, tzv. explicitnĂ
testovánĂ - Druhá moĹľnost je implicitnĂ testovánĂ pomocĂ
prĂkazu WHENEVER
36Explicitnà ošetrenà chyb
- Po vykonánĂ kaĹľdĂ©ho vnorenĂ©ho SQL prĂkazu
obsahuje struktura SQLCA v poli sqlcode kontrolnĂ
hodnotu
Hodnota sqlcode VĂ˝sledek poslednĂho prĂkazu
0 Probehl v porádku
gt 0 Probehl, ale s problĂ©my (warning). Napr. hodnota 100 znacĂ, Ĺľe nebyla nalezena žádná data.
lt 0 Skoncil chybou (error).
37Implicitnà ošetrenà chyb
- ZjednodušenĂ oproti explicitnĂmu ošetrenĂ
- NenĂ treba testovat po kaĹľdĂ©m prĂkazu, testovacĂ
podmĂnka platĂ aĹľ do urcenĂ podmĂnky novĂ© - ZajištenĂ prĂkazem WHENEVER se syntaxĂ
- EXEC SQL WHENEVER ltpodmĂnkagt ltakcegt
38PrĂkaz WHENEVER
- EXEC SQL WHENEVER ltpodmĂnkagt ltakcegt
- Kde ltpodmĂnkagt je
- NOT FOUND (sqlcode je 100, prázdná data),
- SQLWARNING (varovánà jiné než prázdná data),
- SQLERROR (chyba),
- A ltakcegt je
- CONTINUE (program se pokusĂ pokracovat)
- DO ltvolánĂ_funkcegt (zavolánĂ C/C funkce)
- GO TO ltnáveštĂgt (odskok)
- STOP (program ihned skoncĂ)
39Kurzory prĂklad pouĹľitĂ
- EXEC SQL DECLARE osoby_kurzor CURSOR FOR
- SELECT jmeno FROM osoby
- WHERE pocet_deti minimalni_plodnost
- EXEC SQL OPEN osoby_kurzor
- EXEC SQL WHENEVER NOT FOUND DO break
- while(1)
-
- EXEC SQL FETCH emp_cursor INTO jmeno_osoby
-
- EXEC SQL CLOSE osoby_kurzor
40Kurzory FOR UPDATE
- Kurzory slouĹľĂcĂ takĂ© pro Ăşpravu ci mazánĂ
záznamu v tabulce - Kurzor je deklarován s klauzulà FOR UPDATE OF
ltjmĂ©no_tabulkygt na konci - PrĂkazy UPDATE ci DELETE ho mohou vyuĹľĂt v cásti
WHERE, byl-li jiĹľ kurzor otevren a proveden
prĂkaz FETCH - EXEC SQL UPDATE WHERE CURRENT OF osoby_kurzor
- Odkaz na poslednĂ záznam zĂskanĂ˝ prĂkazem FETCH
41Posuvné (scrollable) kurzory
- Dovolujà i jiný pohyb ve vybraných záznamech než
jen o jeden záznam vpred
42Posuvné (scrollable) kurzory
- Dovolujà i jiný pohyb ve vybraných záznamech než
jen o jeden záznam vpred - FETCH FIRST
- FETCH LAST
- FETCH PRIOR
- FETCH NEXT
- FETCH CURRENT
- FETCH RELATIVE n
- FETCH ABSOLUTE n
43ZáverecnĂ˝ prĂklad (1/4)
- include ltstdio.hgt
- / deklarace hostitelských promenných /
- char userid12 "SCOTT/TIGER"
- char jmeno_zamestnance10
- int cislo_zamestanance
- int cislo_oddeleni
- char temp32
- void sql_error()
-
- / SQL Communications Area /
- include ltsqlca.hgt
-
- main()
- emp_number 7499
- / ošetrenà chyb /
- EXEC SQL WHENEVER SQLERROR do
sql_error("Oracle chyba")
44ZáverecnĂ˝ prĂklad (2/4)
- / pripojenà k Oracle databázi /
- EXEC SQL CONNECT userid
- printf(Pripojeno.\n")
-
- / deklarace kurzoru /
- EXEC SQL DECLARE zam_kurzor CURSOR FOR
- SELECT prijmeni
- FROM zam
- WHERE cislo_oddeleni cislo_oddeleni
-
- printf(Cislo oddeleni? ")
- gets(temp)
- dept_number atoi(temp)
-
- / otevrenà kurzoru a vykonánà dotazu /
- EXEC SQL OPEN zam_kurzor
45ZáverecnĂ˝ prĂklad (3/4)
- printf(Prijmeni zamestnance\n")
- printf("-------------\n")
- / nactenĂ dat ve smycce pomocĂ FETCH
- opuštenà smycky, když nebude dalšà rádek /
- EXEC SQL WHENEVER NOT FOUND DO break
- while (1)
-
- EXEC SQL FETCH zam_kurzor INTO
jmeno_zamestnance - printf("s\n", jmeno_zamestnance)
-
- EXEC SQL CLOSE zam_kurzor
- EXEC SQL COMMIT WORK RELEASE
- exit(0)
46ZáverecnĂ˝ prĂklad (4/4)
- void
- sql_error(msg)
- char msg
-
- char buf500
- int buflen, msglen
- EXEC SQL WHENEVER SQLERROR CONTINUE
- EXEC SQL ROLLBACK WORK RELEASE
- buflen sizeof (buf)
- sqlglm(buf, buflen, msglen)
- printf("s\n", msg)
- printf(".s\n", msglen, buf)
- exit(1)
47Konec prezentace
- Cas pro carokrásnou referujĂcà Šárku