vnořené sql ( embedded sql) dotazovací jazyky i

Post on 11-Jan-2016

84 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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

VNOŘENÉ SQL(EMBEDDED SQL)

DOTAZOVACÍ JAZYKY I

Jan SequensMFF 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 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

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

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

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)

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

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

IBM DB2

Oracle

Microsoft SQL Server

MySQL

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

IBM DB2

C/C++, COBOL, FORTRAN, REXX

Oracle

Microsoft SQL Server

MySQL

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

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

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

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;

}

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

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

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;

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

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.

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;

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é.

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);

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;

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;

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í

Příkaz SELECT

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

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;

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

Kurzor

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

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

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

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;

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

OPEN

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

EXEC SQL OPEN osoby_kurzor;

FETCH

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

EXEC SQL FETCH osoby_kurzor

INTO :jmeno_osoby, :prijmeni_osoby;

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.

CLOSE

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

EXEC SQL CLOSE osoby_kurzor;

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

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).

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>;

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čí)

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;

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

Posuvné (scrollable) kurzory

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

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

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");

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;

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); }

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); }

Konec prezentace

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

top related