Vnořené SQL ( embedded SQL) Dotazovací jazyky I

47
VNOŘENÉ SQL (EMBEDDED SQL) DOTAZOVACÍ JAZYKY I Jan Sequens MFF UK, ak. rok 2009/2010

description

Vnořené SQL ( embedded SQL) Dotazovací jazyky I. Jan Sequens MFF UK, ak . rok 2009/2010. Použité zdroje. Chapter 6: Embedded SQL, Pro*C/C++ Precompiler Programmer ’s guide, Release 9.2 , Oracle Corporation http://download.oracle.com/docs/cd/B10501_01/appdev.920/a97269/pc_06sql.htm - PowerPoint PPT Presentation

Transcript of Vnořené SQL ( embedded SQL) Dotazovací jazyky I

Page 1: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

VNOŘENÉ SQL(EMBEDDED SQL)

DOTAZOVACÍ JAZYKY I

Jan SequensMFF UK, ak. rok 2009/2010

Page 2: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Použité zdroje

Chapter 6: Embedded SQL, Pro*C/C++ Precompiler Programmer’s guide, Release 9.2, Oracle Corporation http://download.oracle.com/docs/cd/B10501_01/

appdev.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 Pro*C, Ankur Jain

and Jeff Ullman http://infolab.stanford.edu/~ullman/fcdb/oracle/or-

proc.html Embedded SQL v C/C++, Kateřina Opočenská

http://www.ms.mff.cuni.cz/~kopecky/vyuka/oracle2/ora2_opoc.pdf

Page 3: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Obsah této prezentace

Co je vnořené SQL a jak se používá Hostitelské a indikátorové proměnné Příkazy INSERT, UPDATE, DELETE,

SELECT Kurzory Ošetření chyb

Page 4: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Co a k čemu je vnořené SQL? Způsob použití SQL v programovacích

jazycích SQL vepsané ve zdrojovém kódu jiného

programovacího jazyka Všechny příkazy interaktivního SQL jdou

použít ve vnořeném SQL

Page 5: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Co a k čemu je vnořené SQL? Způsob použití SQL v programovacích

jazycích SQL vepsané ve zdrojovém kódu jiného

programovacího jazyka Všechny příkazy interaktivního SQL jdou

použít ve vnořeném SQL (nikoliv naopak)

Page 6: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme? Náš databázový systém musí mít

podporu vnořeného SQL v našem programovacím jazyce

Page 7: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme?

IBM DB2

Oracle

Microsoft SQL Server

MySQL

Page 8: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme?

IBM DB2

C/C++, COBOL, FORTRAN, REXX

Oracle

Microsoft SQL Server

MySQL

Page 9: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme?

IBM DB2

C/C++, COBOL, FORTRAN, REXX

Oracle

Ada, C/C++, COBOL, Fortran, Pascal, PL/1

Microsoft SQL Server

MySQL

Page 10: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené 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 ukončena oficiální podpora

MySQL

Page 11: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené 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 ukončena oficiální podpora

MySQL

Nepodporováno

Page 12: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme? Příklad vnořeného SQL (Oracle a C):

#include <stdio.h>

#include <sqlca.h>

int main(void)

{

EXEC SQL INSERT INTO osoby (prijmeni) VALUES (‘Sequens’);

return 0;

}

Page 13: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme? Vložíme hlavičkový soubor struktury SQL

Communication Area (SQLCA) Příkazy vnořeného SQL začínáme

direktivou EXEC SQL a ukončujeme středníkem

Page 14: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Jak vnořené SQL používáme? Oracle prostředí pro SQL vnořené v C/C+

+ se nazývá Pro*C/C++ Zdrojové soubory s příponou *.pc Prekompilátor Pro*C/C++ přeloží *.pc na

čistý C/C++ kód Nahrazení konstrukcí vnořeného SQL

voláními standardní run-time knihovny C/C++ kód je standardně zkompilován

Page 15: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Hostitelské proměnné

Předávání dat mezi SQL a C/C++ Ve vnořeném SQL označujeme

dvojtečkou Vstupní

EXEC SQL INSERT INTO osoby (prijmeni) VALUES (:prijmeni_osoby);

Výstupní EXEC SQL SELECT prijmeni

INTO :prijmeni_osoby FROM osoby;

Page 16: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Indikátorové proměnné

Motivace: Co uložit do proměnné, když SELECT vrátí NULL?

Řešení: Použijeme druhou, „spřátelenou“ proměnnou, která bude indikovat, jak a zda je původní proměnná naplněna

Indikátorová proměnná se zapisuje bezprostředně za původní proměnnou, oddělená dvojtečkou

Page 17: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Indikátorové proměnné u výstupních proměnnýchIndikátorová proměnná Hostitelská proměnná

-2 Oříznutá hodnota z databáze, hodnota se do hostitelské proměnné nevejde a její velikost nemůže být určena.

-1 Nedefinovaná hodnota, v databázi byla NULL.

0 Hodnota z databáze, není to NULL.

>0 Oříznutá hodnota z databáze, hodnota se do hostitelské proměnné nevejde. Indikátorová proměnná obsahuje velikost hodnoty v databázi.

Page 18: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Indikátorové proměnné u výstupních proměnných - příklad

EXEC SQL SELECT pocet_deti INTO :pocet:ind_pocet FROM osoby WHERE prijmeni = ‘Sequens’;

if (ind_pocet == -1) /* NULL v databázi */

pocet = 0;

Page 19: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Indikátorové proměnné u vstupních proměnných Ovlivní, co se zapíše do databáze v

příkazech INSERT nebo UPDATE

Indikátorová proměnná Zápis do databáze

-1 Zapíše se NULL (hodnota hostitelské proměnné se bude ignorovat).

>= 0 Zapíše se hodnota hostitelské proměnné.

Page 20: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz INSERT

Stejné použití jako při interaktivním SQL Skutečný zápis proveden až po zapsání

změn příkazem COMMIT

EXEC SQL INSERT INTO osoby (jmeno, prijmeni)

VALUES (:jmeno_osoby, :prijmeni_osoby);

Page 21: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz UPDATE

Stejné použití jako při interaktivním SQL Skutečný zápis proveden až po zapsání

změn příkazem COMMIT

EXEC SQL UPDATE osoby

SET jmeno = :jmeno_osoby

WHERE prijmeni = :prijmeni_osoby;

Page 22: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz DELETE

Stejné použití jako při interaktivním SQL Skutečné smazání provedeno až po

zapsání změn příkazem COMMIT

EXEC SQL DELETE FROM osoby

WHERE prijmeni = :prijmeni_osoby;

Page 23: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz SELECT

V zásadě stejné použití jako u interaktivního SQL

Je třeba vyřešit, kam a jak uložíme to, co SELECT vrátí

Page 24: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz SELECT

Víme-li, že náš SELECT vrátí nejvýše jeden řádek, je situace jednoduchá

Page 25: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz SELECT

Víme-li, že náš SELECT vrátí nejvýše jeden řádek, je situace jednoduchá

EXEC SQL SELECT jmeno, prijmeni

INTO :jmeno_osoby, :prijmeni_osoby

FROM osoby;

Page 26: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz SELECT

Víme-li, že náš SELECT vrátí nejvýše jeden řádek, je situace jednoduchá

EXEC SQL SELECT jmeno, prijmeni

INTO :jmeno_osoby, :prijmeni_osoby

FROM osoby;

Vrací-li SELECT více než jeden řádek, je třeba použít ke zpracování výsledku tzv. kurzor

Page 27: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Kurzor

Nástroj pro práci s množinou řádků, kterou vrací příkaz SELECT

Udržuje ukazatel na aktuální zpracovávaný řádek

Page 28: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Princip práce s kurzorem

DECLARE CURSOR Určení SQL dotazu, se kterým bude kurzor

pracovat OPEN

Provedení SQL dotazu, se kterým kurzor pracuje

FETCH Načtení jednoho řádku z výsledku dotazu

CLOSE Ukončení práce s kurzorem

Page 29: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

DECLARE CURSOR

Pojmenování kurzoru Asiociace s dotazem

EXEC SQL DECLARE osoby_kurzor CURSOR FOR

SELECT jmeno, prijmeni

FROM osoby

WHERE pocet_deti > :minimalni_plodnost;

Page 30: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

DECLARE CURSOR

Pojmenování kurzoru Asiociace s dotazem

EXEC SQL DECLARE osoby_kurzor CURSOR FOR

SELECT jmeno, prijmeni

FROM osoby

WHERE pocet_deti > :minimalni_plodnost;

Nezahrnujeme klauzuli INTO

Page 31: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

OPEN

Navázání hostitelských proměnných Vykonání dotazu

EXEC SQL OPEN osoby_kurzor;

Page 32: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

FETCH

Načtení řádku z výsledku Posunutí ukazatele na další řádek

EXEC SQL FETCH osoby_kurzor

INTO :jmeno_osoby, :prijmeni_osoby;

Page 33: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

FETCH

Načtení řádku z výsledku Posunutí ukazatele na další řá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 otevřen.

Page 34: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

CLOSE

Uzavře kurzor, uvolní zdroje. Posunutí ukazatele na další řádek

EXEC SQL CLOSE osoby_kurzor;

Page 35: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Ošetření chyb

Ke smysluplnému příkladu použití kurzoru nám chybí způsob, jak ošetřit chyby

První možnost je testovat po každém vnořeném SQL příkazu, zda-li nedošlo k chybě, tzv. explicitní testování

Druhá možnost je implicitní testování pomocí příkazu WHENEVER

Page 36: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Explicitní ošetření chyb

Po vykonání každého vnořeného SQL příkazu obsahuje struktura SQLCA v poli sqlcode kontrolní hodnotu

Hodnota sqlcode Výsledek posledního příkazu

0 Proběhl v pořádku

> 0 Proběhl, ale „s problémy“ (warning). Např. hodnota 100 značí, že nebyla nalezena žádná data.

< 0 Skončil chybou (error).

Page 37: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Implicitní ošetření chyb

Zjednodušení oproti explicitnímu ošetření

Není třeba testovat po každém příkazu, testovací podmínka platí až do určení podmínky nové

Zajištění příkazem WHENEVER se syntaxí:

EXEC SQL WHENEVER <podmínka> <akce>;

Page 38: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Příkaz WHENEVER

EXEC SQL WHENEVER <podmínka> <akce>; Kde <podmínka> je

NOT FOUND (sqlcode je 100, prázdná data), SQLWARNING (varování jiné než prázdná data), SQLERROR (chyba),

A <akce> je CONTINUE (program se pokusí pokračovat) DO <volání_funkce> (zavolání C/C++ funkce) GO TO <návěští> (odskok) STOP (program ihned skončí)

Page 39: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Kurzory – pří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;

Page 40: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Kurzory FOR UPDATE

Kurzory sloužící také pro úpravu či mazání záznamů v tabulce

Kurzor je deklarován s klauzulí FOR UPDATE OF <jméno_tabulky> na konci

Příkazy UPDATE či DELETE ho mohou využít v části WHERE, byl-li již kurzor otevřen a proveden příkaz FETCH EXEC SQL UPDATE … WHERE CURRENT OF osoby_kurzor;

Odkaz na poslední záznam získaný příkazem FETCH

Page 41: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Posuvné (scrollable) kurzory

Dovolují i jiný pohyb ve vybraných záznamech než jen o jeden záznam vpřed

Page 42: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Posuvné (scrollable) kurzory

Dovolují i jiný pohyb ve vybraných záznamech než jen o jeden záznam vpřed FETCH FIRST FETCH LAST FETCH PRIOR FETCH NEXT FETCH CURRENT FETCH RELATIVE n FETCH ABSOLUTE n

Page 43: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Závěrečný příklad (1/4)

#include <stdio.h>

/* deklarace hostitelských proměnných */ char userid[12] = "SCOTT/TIGER";char jmeno_zamestnance[10];int cislo_zamestanance;int cislo_oddeleni; char temp[32];void sql_error(); /* SQL Communications Area */ #include <sqlca.h> main() { emp_number = 7499;/* ošetření chyb */ EXEC SQL WHENEVER SQLERROR do sql_error("Oracle chyba");

Page 44: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Závěrečný příklad (2/4)

/* připojení 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); /* otevření kurzoru a vykonání dotazu */ EXEC SQL OPEN zam_kurzor;

Page 45: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Závěrečný příklad (3/4)

printf(„Prijmeni zamestnance\n"); printf("-------------\n");/* načtení dat ve smyčce pomocí FETCHopuštění smyčky, když nebude další řá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); }

Page 46: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Závěrečný příklad (4/4)

void sql_error(msg)char *msg;{ char buf[500]; 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); }

Page 47: Vnořené SQL ( embedded  SQL) Dotazovací jazyky I

Konec prezentace

Čas pro čarokrásnou referující Šárku