Embedded C výjimky, kurzory. Šárka Hlušičková

Podobné dokumenty
Embedded SQL v C/C++ úvod. Administrace Oracle Kateřina Opočenská

Embedded SQL Dotazovací Jazyky I. Bc. CHOMUT Miroslav Bc. VODOLÁN Miroslav

Embedded SQL. Tomáš Skalický. Říjen 2010

PL/SQL. Jazyk SQL je jazykem deklarativním, který neobsahuje procedurální příkazy jako jsou cykly, podmínky, procedury, funkce, atd.

Embedded SQL v C/C++ III - pole, struktury. Jindřich Vodrážka

Distanční opora předmětu: Databázové systémy Tématický blok č. 8: Transact SQL Autor: RNDr. Jan Lánský, Ph.D.

Databáze I. Přednáška 9

Text úlohy. Systémový katalog (DICTIONARY):

Kurz Databáze. Obsah. Dotazy. Zpracování dat. Doc. Ing. Radim Farana, CSc.

Návrh a tvorba WWW stránek 1/14. PHP a databáze

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

10. Architektura klient/server a třívrstvá architektura

10. Architektura klient/server a třívrstvá architektura

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Dotazovací jazyk SQL a PL/SQL. 8. Přednáška

Západočeská univerzita v Plzni Katedra informatiky a výpočetní techniky. 9. června krovacek@students.zcu.cz

Databáze 2011/2012 T-SQL - kurzory, funkce. RNDr.David Hoksza, Ph.D.

Informační systémy 2008/2009. Radim Farana. Obsah. Skripty a dávky. Nastavení aktuální databáze. USE DatabaseName

Informační systémy 2008/2009. Radim Farana. Obsah. Jazyk SQL

Databázové systémy. - SQL * definice dat * aktualizace * pohledy. Tomáš Skopal

Vkládání, aktualizace, mazání

2. blok část B Základní syntaxe příkazů SELECT, INSERT, UPDATE, DELETE

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

SQL. strukturovaný dotazovací jazyk. Structured Query Language (SQL)

Informační systémy 2008/2009. Radim Farana. Obsah. Dotazy přes více tabulek

Popis programovacího jazyka PL/SQL

Deklarativní IO shrnutí minulé přednášky

Jazyk PL/SQL Úvod, blok

Databázové systémy. Dotazovací jazyk SQL - III

Databáze I. 5. přednáška. Helena Palovská

6. blok část B Vnořené dotazy

Databázové systémy I

Operační systémy. Cvičení 4: Programování v C pod Unixem

Strukturu lze funkci předat: (pole[i])+j. switch(výraz) velikost ukazatele

Programování v C++ 1, 1. cvičení

Kapitola 4: SQL. Základní struktura

Oracle Call Interface (OCI)

Databázové systémy Cvičení 5.2

Stored Procedures & Database Triggers, Tiskové sestavy v Oracle Reports

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

MySQLi (objektově) Příklad vytvoření instance třídy včetně parametrů pro připojení: $mysqli = new mysqli('localhost', 'login', 'heslo', 'databaze');

GUIDELINES FOR CONNECTION TO FTP SERVER TO TRANSFER PRINTING DATA

Popis souboru pro generování reportů *.report

PRŮBĚHOVÝ TEST Z PŘEDNÁŠEK

DATABÁZOVÉ A INFORMAČNÍ SYSTÉMY

4. lekce Přístup k databázi z vyššího programovacího jazyka

6. Příkazy a řídící struktury v Javě

6 Příkazy řízení toku

řízení transakcí 2-3 hodiny

Databáze I. Přednáška 4

Algoritmizace a programování. Ak. rok 2012/2013 vbp 1. ze 44

3. Jazyky relačních databázových systémů

Jazyk SQL databáze SQLite. připravil ing. petr polách

PG 9.5 novinky ve vývoji aplikací

Databáze SQL SELECT. David Hoksza

Př. další použití pointerů

Úvod do programování - Java. Cvičení č.4

Oracle XML DB. Tomáš Nykodým

XMW4 / IW4 Pokročilé SELECT dotazy. Štefan Pataky

7. Integrita a bezpečnost dat v DBS

7. Integrita a bezpečnost dat v DBS

KIV/ZIS cvičení 6. Tomáš Potužák

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

Z. Kotala, P. Toman: Java ( Obsah )

Zápisování dat do databáze

Např.: // v hlavičkovém souboru nebo na začátku // programu (pod include): typedef struct { char jmeno[20]; char prijmeni[20]; int rok_nar; } CLOVEK;

InnoDB transakce, cizí klíče, neumí fulltext (a nebo už ano?) CSV v textovém souboru ve formátu hodnot oddělených čárkou

Virtual Private Database (VPD) Jaroslav Kotrč

Větvení a cykly. Úvod do programování 1 Tomáš Kühr

- jak udělat konstantu long int: L long velka = 78L;

IBM DB2 Universal Database. Přehled zpráv, díl 2. verze 7 GC

Databázové systémy II. KIV/DB2 LS 2007/2008. Zadání semestrální práce

MQL4 COURSE. V tomto dodatku je obsažen popis 25 obchodních funkcí jazyka MQL4. Rozhodl jsem se napsat

Databázové systémy Cvičení 5.3

Transakce a zamykání Jiří Tomeš

Cykly. Základy programování 1 Martin Kauer (Tomáš Kühr)

Optimalizace dotazů a databázové transakce v Oracle

Co se stane po jeho vykonání? Vyberte libovolný počet možných odpovědí. Správná nemusí být žádná, ale také mohou být správné všechny.

Integritní omezení (IO)

DJ2 rekurze v SQL. slajdy k přednášce NDBI001. Jaroslav Pokorný

Řídicí struktury. alg3 1

NÁVRH A TVORBA HUDEBNÍ DATABÁZE

Obchodní akademie a Jazyková škola s právem státní jazykové zkoušky Jihlava

DSA, První krok: máme dokázat, že pro left = right vrátí volání f(array, elem, left, right)

UPM3 Hybrid Návod na ovládání Čerpadlo UPM3 Hybrid 2-5 Instruction Manual UPM3 Hybrid Circulation Pump 6-9

6. blok část C Množinové operátory

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

PB071 Programování v jazyce C

3. Jazyky relačních databázových systémů

Novinky v PostgreSQL 9.4. Tomáš Vondra, 2ndQuadrant

x86 assembler and inline assembler in GCC

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Základní přehled SQL příkazů

7. Datové typy v Javě

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 10.4.

Databáze. Velmi stručný a zjednodušený úvod do problematiky databází pro programátory v Pythonu. Bedřich Košata

MySQL sežere vaše data

Transkript:

Embedded C výjimky, kurzory Šárka Hlušičková

Obsah Indikátorové proměnné informace o obsahu hostitelských proměnných SQLCA, whenever klauzule ošetření běhových chyb Kurzory zpracování víceřadkových výsledků selectu

Indikátorové proměnné Každou hostitelskou proměnnou je možné asociovat s indikátorovou proměnnou (2-byte integer short), deklarace v deklarační částí jako hostitelské proměnné Asociovaná indikátorová proměnná indikuje,co je v hostitelské proměnné uloženo za hodnotu (detekce NULL hodnot, ořezání...) V SQL příkazech musí být uvozena dvojtečkou a musí následovat svou hostitelskou proměnnou Příklad: :employee:ind_emp kde employee je hostitelská a ind_emp je indikátorová

Vstup Výstup Indikátorové proměnné - pokračování Hodnota indikátor. proměnné Význam -1 Hodnota hostitelské proměnné je interpretována jako NULL, skutečná hodnota se ignoruje >=0 Bere se skutečná hodnota hostitelské proměnné Hodnota indikator. proměnné Význam -1 Ve sloupci je NULL, takže hodnota hostitelské proměnné je nedefinována 0 V hostitelské proměnné je celá hodnota >0 Hodnota v hostitelské proměnné byla ořezána, v indikátorové je původní délka hodnoty, SQLCODE v SQLCA je nastaven na 0-2 Hodnota v hostitelské byla ořezána, ale nelze určit původní velikost

Příklad použití indikátorových proměnných při insertu printf("enter employee number or 0 if not available: "); scanf("%d", &emp_number); if (emp_number == 0) ind_empnum = -1; else ind_empnum = 0; EXEC SQL INSERT INTO emp (empno, sal) VALUES (:emp_number:ind_empnum, :salary);

Příklad použití indikátorových proměnných při selectu EXEC SQL SELECT ename, sal, comm INTO :emp_name, :salary, :commission:ind_comm FROM emp WHERE empno = :emp_number; if (ind_comm == -1) pay = salary; /* commission is NULL, ignore it */ else pay = salary + commission;

Příklad použití indikátorových proměnných při selectu II Testování NULL ve WHERE klauzuli EXEC SQL SELECT ename, sal INTO :emp_name, :salary FROM emp WHERE :commission INDICATOR :ind_comm IS NULL... Porovnávání s možnou NULL hodnotou EXEC SQL SELECT ename, sal INTO :emp_name, :salary FROM emp WHERE (comm = :commission) OR ((comm IS NULL) AND :commission INDICATOR :ind_comm IS NULL));

Ošetření běhových chyb s použitím SQLCA SQL Communications Area slouží k detekci chyb a zjištění změn ve statusech Struktura, jejíž položky plní Oracle při každém provedení SQL příkazu #include <sqlca.h> nebo EXEC SQL INCLUDE SQLCA; (mimo deklarační část, MODE=ORACLE) Dva způsoby: Implicitní, pomocí klauzule WHENEVER Explicitní, přímo pomocí SQLCA položek

sqlglm funkce SQLCA obsahuje chybové zprávy o maximální délce 70 znaků Dlouhé nebo vnořené zprávy je možné získat funkcí sqlglm() void sqlglm(char *message_buffer, size_t *buffer_size, size_t *message_length); kde message_length obsahuje aktuální délku chybové zprávy (max 512 znaků)

WHENEVER klauzule Standardně jsou Oracle chyby a varování ignorovány a program pokračuje, pokud je to možné Automatické zachytávání chyb je lze zajistit pomocí WHENEVER klauzule (něco jako výjimky) Jakmile je detekována podmínka, je provedena akce EXEC SQL WHENEVER <condition> <action>; Kde podmínkou může být SQLWARNING SQLERROR NOT FOUND (kritériu v SELECT neodpovídá žádný řádek, FETCH/SELECT INTO nevrátil žádný řádek)

CONTINUE DO Defaultní akce WHENEVER akce Provede se funkce, která chybu ošetří, po jejím skončení program pokračuje příkazem následujím po tom, kde nastala chyba Je možné funkci předat parametry a použít její návratovou hodnotu STOP Program skončí (volá se exit()) a je proveden rollback

WHENEVER akce pokračování DO BREAK Použití v cyklu, jakmile nastane podmínka, cyklus skončí DO CONTINUE Použití v cyklu, jakmile nastane podmínka program pokračuje další iterací GOTO label Program pokračuje na místě, kde je příslušné návěští Délka jména návěští je omezena (31 znaků)

Příklad WHENEVER DO EXEC SQL WHENEVER SQLERROR DO handle_insert_error("insert error"); EXEC SQL INSERT INTO emp (empno, ename, deptno) VALUES (:emp_number, :emp_name, :dept_number);... handle_insert_error(char *stmt) { switch(sqlca.sqlcode) { case -1: /* duplicate key value */... break; case -1401: /* value too large */... break; default: /* do something here too */... break; } }

Platnost WHENEVER Deklarativní příkaz, záleží na fyzické pozici, neřídí se logickým během programu Klauzule testuje všechny fyzicky následující příkazy, dokud není nahrazena jinou, testující stejnou podmínku

Příklad platnost WHENEVER První WHENEVER SQLERROR se aplikuje jen na CONNECT, pak je nahrazenou druhou Druhá WHENEVER SQLERROR se aplikuje na UPDATE i na DROP, ačkoli program step2 preskočí step1: EXEC SQL WHENEVER SQLERROR STOP; EXEC SQL CONNECT :username IDENTIFIED BY :password;... goto step3; step2: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL UPDATE emp SET sal = sal * 1.10;... step3: EXEC SQL DROP INDEX emp_index;...

Doporučení Pozor na nekonečné cykly při volání WHENEVER Návěští musí být dosažitelné ze všech odkazovaných GOTO

Kurzory Pomáhají zpracovávat víceřádkové výsledky dotazů Umožňují procházet jednotlivé řádky (udržují si přehled, který řádek má být zpracován) Příkazy pro manipulaci s kurzory: DECLARE CURSOR pojmenuje kurzor a sváže ho s dotazem OPEN vykoná dotaz a z výsledků dotazu vytvoří tzv. active set FETCH vrátí aktuální řádek ze setu, opakovaným voláním vrátí všechny CLOSE zavře kurzor, active set není definován

DECLARE CURSOR EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, empno, sal FROM emp WHERE deptno = :dept_number; Je možné deklarovat tolik kurzorů, kolik je třeba (omezení je v proměnné MAXOPENCURSORS) Jméno kurzoru má globální platnost v rámci souboru SELECT příkaz nesmí obsahovat INTO, INTO je možné použít v příkazu FETCH Všechny příkazy k danému kurzoru musí být v jedné prekompilované jednotce

OPEN Vykoná dotaz a vytvoří tzv. active set EXEC SQL OPEN emp_cursor; OPEN vynuluje počet zpracovaných řádek, ale řádky samotné zatím viditelné nejsou, kurzor je před první řádkou active setu Po otevření se už změna v hodnotách hostitelských proměnných v dotazu neprojeví, je třeba znovu otevřít kurzor, aby se aktualizovali výsledky a tedy active set Při znovu otevírání je třeba buď kurzor nejprve zavřít (MODE=ANSI), nebo mít nastaveno MODE=ORACLE (default, rychlejší)

FETCH Získá aktuální řádek z active setu a naplní výstupní hostitelské proměnné, tj. INTO a seznam hostitelských proměnných může být součástí FETCH příkazu EXEC SQL FETCH emp_cursor INTO :emp_name, :emp_number, :salary; Fetch je možný jen z otevřeného kurzoru První vykonání přesune kurzor na první řádek active setu aktuální řádka Další vykonání fetch přesune kurzor na další řádek nová aktuální řádka... aby se uživatel vrátil k již zpracované řádce, je nutné znovuotevřít kurzor

FETCH pokračování Je možné provést FETCH pokaždé s jimými výstupnímu hostitelskými proměnnými (ale stejného typu): EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, sal FROM emp WHERE deptno = 20;... EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND GOTO... for (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name1, :salary1; EXEC SQL FETCH emp_cursor INTO :emp_name2, :salary2;... }

FETCH pokračování II Pokud je active set prázdný nebo už neobsahuje žádné další řádky vrací FETCH chybu: chybový kód no data found v SQLCA, nebo ve status proměnných SQLCODE či SQLSTATE, Při chybě no data found hodnota výstupních proměnných není daná Obvykle se tato chyba zachycuje pomocí WHENEVER NOT FOUND Pokud chceme číst i pak, je třeba kurzor znovu otevřít

CLOSE EXEC SQL CLOSE emp_cursor; Uvolní zdroje, které konkrétně se nastaví pomocí voleb HOLD_CURSOR a RELEASE_CURSOR Po uzavření není možné na kurzor použít fetch, active set není definován Příkazy COMMIT a ROLLBACK při MODE=ORACLE, zavřou kurzory v podmínce CURRENT OF, ostatní ponechají jak jsou. při MODE=ANSI, se zavřou všechny explicitní kurzory, lze změnit nastavením CLOSE_ON_COMMIT na NO.

Příklad... EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename,job FROM emp WHERE empno =:emp_number; EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND DO break; for (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name, :job_title;... }... EXEC SQL CLOSE emp_cursor; EXEC SQL COMMIT WORK RELEASE;...

Scrollable cursor Umožnuje přistupovat k řádkům setu i jinak než sekvenčně Příklad: EXEC SQL DECLARE emp_cursor SCROLL CURSOR FOR SELECT ename, sal FROM emp WHERE deptno=20;... EXEC SQL OPEN emp_cursor; EXEC SQL FETCH LAST emp_cursor INTO :emp_name, :sal; EXEC SQL CLOSE emp_cursor;...

Scrollable cursor pokračování Přehled FETCH příkazů: FETCH --náhodně FETCH FIRST --první řádek setu FETCH PRIOR --řádka předcházející aktuální FETCH NEXT --řádka následující za aktuální FETCH LAST --poslední řádka setu FETCH CURRENT --aktuální řádka FETCH RELATIVE n --n-tá řádka relativně vůči aktuální FETCH ABSOLUTE n -- n-tá řádka setu

CURRENT OF klauzule Klauzuli je možné použít v DELETE nebo UPDATE příkazu jako odkaz na aktuální řádku (vrácenou posledním FETCH) Pokud žádná aktuální řádka není, příkaz se neprovede a vrátí chybu

Příklad CURRENT OF EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, sal FROM emp WHERE job = 'CLERK' FOR UPDATE OF sal;... EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND GOTO for (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name, :salary;... } EXEC SQL UPDATE emp SET sal = :new_salary WHERE CURRENT OF emp_cursor;

FOR UPDATE OF klauzule Používá se, když deklaruje kurzor, který je odkazován klauzulí CURRENT OF v UPDATE nebo DELETE příkazu Získá exkluzivní zámky na daných řádcích, vhodné například když upravuje hodnoty na základě stávajících Řádky jsou zamčeny při OPEN, po COMMITU/ROLLBACKU (ale ne k savepointu) jsou uvolněny, tj. pak už nelze udělat FETCH V případě použití CURRENT OF klauzule je použití FOR UPDATE OF volitelná, prekompilátor si ji kdyžtak doplní

Kompletní příklad 1 http://docs.oracle.com/cd/e11882_01/appdev.112/e10825 /pc_06sql.htm#i2240 #include <stdio.h> /* declare host variables */ char userid[12] = "SCOTT/TIGER"; char emp_name[10]; int emp_number; int dept_number; char temp[32]; void sql_error(); /* include the SQL Communications Area */ #include <sqlca.h>

Kompletní příklad 1 pokračování main() { emp_number = 7499; /* handle errors */ EXEC SQL WHENEVER SQLERROR do sql_error("oracle error"); /* connect to Oracle */ EXEC SQL CONNECT :userid; printf("connected.\n"); /* declare a cursor */ EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename FROM emp WHERE deptno = :dept_number; printf("department number? "); gets(temp); dept_number = atoi(temp);

Kompletní příklad 1 pokračování II /* open the cursor and identify the active set */ EXEC SQL OPEN emp_cursor; printf("employee Name\n"); printf("-------------\n"); /* fetch and process data in a loop exit when no more data */ EXEC SQL WHENEVER NOT FOUND DO break; while (1) { EXEC SQL FETCH emp_cursor INTO :emp_name; printf("%s\n", emp_name); } EXEC SQL CLOSE emp_cursor; EXEC SQL COMMIT WORK RELEASE; exit(0); } /* main */

Kompletní příklad 1 pokračování III void sql_error(msg) char *msg; { char buf[500]; int buflen, msglen; EXEC SQL WHENEVER SQLERROR CONTINUE; /* to avoid infinite loop when rollback fails*/ EXEC SQL ROLLBACK WORK RELEASE; } buflen = sizeof (buf); sqlglm(buf, &buflen, &msglen); /* gets full msg*/ printf("%s\n", msg); printf("%*.s\n", msglen, buf); exit(1);

Kompletní příklad 2 http://docs.oracle.com/cd/e11882_01/appdev.112/e10825/pc_09err.htm#sthref1288 #include <sqlca.h> #include <stdio.h> main() { char *uid = "scott/tiger"; struct { char ename[12]; float sal; float comm; } emp; /* Trap any connection error that might occur. */ EXEC SQL WHENEVER SQLERROR GOTO whoops; EXEC SQL CONNECT :uid; EXEC SQL DECLARE c CURSOR FOR SELECT ename, sal, comm FROM EMP ORDER BY ENAME ASC; EXEC SQL OPEN c;

Kompletní příklad 2 pokračování I /* Set up 'BREAK' condition to exit the loop. */ EXEC SQL WHENEVER NOT FOUND DO BREAK; /* The DO CONTINUE makes the loop start at the next iteration when an error occurs.*/ EXEC SQL WHENEVER SQLERROR DO CONTINUE; while (1) { EXEC SQL FETCH c INTO :emp; /* An ORA-1405 would cause the 'continue' to occur. So only employees with non-null commissions will be displayed. */ printf("%s %7.2f %9.2f\n", emp.ename, emp.sal, emp.comm); }

Kompletní příklad 2 pokračování II /* This 'CONTINUE' shuts off the 'DO CONTINUE' allowing the program to proceed if any further errors do occur, specifically, with the CLOSE */ EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL CLOSE c; exit(exit_success); whoops: printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); exit(exit_failure); }

Zdroje Pro*C/C++ Programmer's Guide 11g Release 2 (11.2) [online], kap. 6 Embedded SQL, dostupné na: http://docs.oracle.com/cd/e11882_01/appdev.112/e10825/pc_06sql.htm#g19457 Pro*C/C++ Programmer's Guide 11g Release 2 (11.2) [online], kap. 9 Handling Runtime Errors, dostupné na: http://docs.oracle.com/cd/e11882_01/appdev.112/e10825/pc_09err.htm#g35612