1 Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) ABR 2( Adatbázisrendszerek 2) 2.Előadás: Tárolt eljárások
2 Tárolt eljárások MySQL-ben Tárolt eljárások definíciója Tárolt rutinok használata (eljárások és függvények) –Tárolt rutinok szintaxisa –Tárolt rutinok és MySQL privilégiumok –Tárolt rutinok meta-adatai –Tárolt eljárások, függvények, triggerek és LAST_INSERT_ID()
3 Tárolt eljárások definíciója Minden tárolt program tartalmaz egy törzs részt amelyik egy SQL utasítást tartalmaz. Ez az utasítás lehet egy összetett utasítás, amelyet több utasítás alkot, amelyeket pontosvessző (;) karakter választ el. Például, a következő tárolt eljárás egy BEGIN... END blokk között készült, amelyik tartalmaz egy SET utasítást és egy REPEAT ciklust, amelyik megint tartalmaz egy másik SET utasítást:
4 CREATE PROCEDURE dorepeat(p1 INT) BEGIN = 0; REPEAT + 1; > p1 END REPEAT; END Ugyanúgy, mint a triggerek esetében, ahhoz, hogy a pontosvesző (;) gondot okozhat, mert a mysql kliens utasítás határolójeleként ismeri fel. Ezért a határolójelet (delimiter) át kell neveznünk, hogy a mysql átadja a tárolt programdefiníciót a szervernek. Hogy újra- definiáljuk használjuk a delimiter parancsot.
5 delimiter // CREATE PROCEDURE dorepeat(p1 INT) BEGIN = 0; REPEAT + 1; > p1 END REPEAT; END delimiter ; mysql> CALL dorepeat(1000); mysql> | |1001|
6 Függvény, amelyik egy belső függvényt hív meg CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT('Hello, ',s,'!'); SELECT hello('world'); | hello('world') | | Hello, world! |
7 Tárolt rutinok szintaxisa EljárásCREATE PROCEDURE FüggvényCREATE FUNCTION Eljárás meghívása CALL segítségével Függvény meghívató egy utasítás belsejéből ugyanúgy, mint más függvény (felhasználva a függvény nevét) és skalár értéket kapunk Rutinok megszűntetése DROP PROCEDURE és DROP FUNCTION Módosítása ATER PROCEDURE és ALTER FUNCTION
8 Tárolt eljárás vagy függvény egy adatbázishoz van kapcsolva 1.Amikor egy rutin meghívásra kerül, egy implicit USE db_name végződik el (és visszaforog mikor a rutin befejeződik). USE utasítás a tárolt rutinok belsejében nem megengedett 2.Minősíthetjük a rutin neveket az adatbázis nevek használatával. Ezt használhatjuk, hogy vonatkoztassunk egy olyan rutinra, mely nem ehhez az adatbázisoz tartozik. Például, hogy meghívjunk egy tárolt p eljárást vagy f függvényt, amelyik a test adatbázisoz tartoznak, haszálhatjuk a CALL test.p() vagy test.f()-t. 3.Amikor az adatbázis törlődik, minden vele kapcsolatos rutin törlődik úgyszintén.
9 Tárolt függvények NEM lehetnek rekurzívak Tárolt eljárás lehet rekurzív, de alap- értelmezetten ki van kapcsolva. Hogy jóváhagyjuk a rekurziót, állítsuk be a max_sp_recursion_depth szerver rendszer- változót egy zérónál nagyobb értékre. Tárolt eljárás rekurzivitása megnöveli a szál veremméretét. Ha megnöveljük az értékét a max_sp_recursion_depth-nek, lehetséges, hogy szükséges megnövelni a szálak veremméretét, megnövelve a thread_stack értékét a szerver indításakor.
10 Többszörös SELECT az eljárás belsejében MySQL támogatja azt a nagyon hasznos kiterjesztést, amelyik megengedi, a normál SELECT utasítás használatát (kurzorok és lokális változók nékül) egy tárolt eljárás besejében. Az eredmény halmaza az ilyen lekérdezésnek egyszerűen el van küldve a kliensnek. Többszörös SELECT utasítás többszörös eredmény halmazt generál, tehát a kliensnek használnia kell azt a MySQL kliens könyvtárat, amelyik többszörös eredmény halmazt tud kezelni. Ez azt jelenti, hogy a MySQL verzió legalább 4.1.-es. A kliensnek ugyanakkor kell specifikálja a CLIENT_MULTI_RESULTS opciót miközben kapcsolatot teremt. A C programoknál, ezt el lehet érni a mysql_real_connect() C API függvénnyel.
11 Tárolt rutinok és MySQL privilégiumok A CREATE ROUTINE privilégium szükséges hogy tárolt rutinokat készítsünk Az ATER ROUTINE privilégium szükséges ahhoz, hogy módosítsunk vagy töröljünk tárolt eljárásokat. Ez a privilégium automatikusan meg van adva a rutin készítőjének ha szükséges és eldobva a készítőtől, mikor dobva van. Az EXECUTE privilégium szükséges hogy futtatni tudjunk tárolt rutinokat. Ez a privilégium automatikusan adott a rutin készítőjének ha szükséges. (és eldobódik mikor a rutin törlődik). Ugyanakkor, az alapértelmezett SQL SECURITY karakterisztikája egy rutinnak a DEFINER, amelyik megengedi azon felhasználóknak, akik elérhetik azt az adatbázist amelyhez kapcsolódik a rutin, hogy futtathassák.
12 Tárolt rutinok meta-adatai Lekérdezzük a ROUTINES táblát az INFORMATION_SCHEMA adatbázisból Használjuk a SHOW CREATE PROCEDURE és SHOW CREATE FUNCTION utasításokat hogy lássuk a rutin definciókat. Használjuk a SHOW PROCEDURE STATUS és a SHOW FUNCTION STATUS utasításokat, hogy lássuk a rutin karaterisztikát.
13 Tárolt eljárások, függvények, triggerek és LAST_INSERT_ID() LAST_INSERT_ID() (argumentum nélkül) visszaadja az első automatikusan generált értékét egy AUTO_INCREMENT oszlopnak, mint egy eredményét a legutolsó elvégzett INSERT utasításnak. Egy tárolt rutin törzsében (eljárás vagy fügvény) vagy egy triggerben, az LAST_INSERT_ID() értéke ugyanúgy változik, mint azon utasításoknál, melyek a törzsön kívül hajtóak végre. Ha egy tárolt eljárás végrehajt olyan utasításokat, amelyek megváltoztatják a LAST_INSERT_ID() értékét, a megváltozott értéket látják az elkövetkező utasítások, melyek következnek az eljárás meghívása után. A tárolt függvények és triggerek esetében ez az érték visszatöltődik amikor a függvény vagy a trigger befejezi működését, a következő utasítások nem látják már az újat.
14 BEGIN... END összetett szintaxis [begin_label:] BEGIN [statement_list] END [end_label] [statement_list] egy vagy több utasítás, elválasztva a (;)-vel [end_label] nem létezhet a [begin_label:] nélkül. Ha létezik [begin_label:] és [end_label], ugyanazok kell legyenek A cimkék maximum 16 karakteresek kell legyenek Cimkék használata engedélyezve van a LOOP, REPEAT és a WHILE utasításokban is
15 DECLARE szintaxisa Arra használjuk, hogy különböző adatot definiáljunk egy lokális programhoz: Lokális változók. Feltételek és kezelők (handlers) Kurzorok. DECLARE használata csak a BEGIN...END összetett utasítás belsejében megengedett és az elején kell legyen, más utasítások előtt. A nyilatkozatok be kell tartsanak bizonyos sorrendet. A kurzorokat a kezelők előtt kell deklarálni és a változókat és feltételeket a kurzorok és handlerek előtt.
16 Lokális változók deklarációja DECLARE var_name [, var_name]... type [DEFAULT value] Hogy alapértelmezett értéket adjunk a változóknak, használjuk a DEFAULT záradékot. Az érték lehet egy kifejezés, nem szükségszerűen konstans érték. Ha em használjuk a DEFAULT záradékot, a kezdő érték NULL. Helyi változók ugyanúgy vannak kezelve, mint tárolt rutinok paraméterei, figyelembe véve az adattípust és a túlcsordulást. Lokális változók nem érzékenyek a NAGYBETŰ/kisbetűre. A lokális változó hatóköre a BEGIN...END blokk, ahol deklarálva volt. A változókat, a deklarált blokk beágyazott blokkjában is használhatjuk, kivéve, ha ugyanazon a néven új változót deklaráluk a beágyazott blokkban.
17 Lokális változók beállítása (SET) SET var_name = expr [, var_name = expr]... A SET záradék a tárolt eljárásokban az általános SET záradék kiterjesztése. Minden var_name egy lokális változóra hivakozik egy tárolt programon belül, egy rendszer változó vagy egy felhasználó által definiált változó. A SET záradék a tárolt programokban a létező SET szintaxis részeként van implementálva. Ez megengedi egy kiterjesztett szintaxisát a SET a=x, b=y,... ahol különböző változó tipusok (lokálisan deklarált változók, globális és session rendszer változók, felhasználó-definiált változók) keveredhetnek. Ez megengedi a lokális változók kombinációit és néhány opciót, amelyik csak a rendszerváltozókra értelmezett; ebben az esetben az opciók felismerve lesznek, viszont mellőzve.
18 SELECT...INTO szintaxisa SELECT col_name [, col_name]... INTO var_name [, var_name]... table_expr Ez a szintaxis megengedi hogy a kiválasztott oszopokat direkt módon tárolhassuk változókban. Ha a lekérdezés nem ad vissza egy sort sem, egy figyelmeztető 1329 kóddal jelzi a hibát és a változó értékek nem változnak. Ha a lekérdezés több sort eredményez, egy más hibát jelez a rendszer. Ha lehetséges, hogy a lekérdezés több sort adjon vissza, hasznájuk a Limit 1 direktívát. Felhasználó nevek nem érzékenyek a betűagyságra.
19 A lokális változók hatásköre A lokális változó hatásköre azon BEGIN...END között van, ahol az deklaráltuk. Hivatkozni lehet ezekre beágyazott blokkokból is, kivéve, ha a blokkokban egy ugyanolyan nevű változót használunk. Lokális változók a tárolt eljárás végrehajtása során léteznek, előkészített utasítások nem használhatják, mivel ezek globálisak a kurrens sessionban és meghaladhatják a hatáskörüket. Például a SELECT... INTO local_var nem használható, mint előkészített utasítás. Lokális változóknak a nevei nem egyezhetnek meg az oszlopnevekkel. Ha egy SQL utasítás, mint a SELECT...INTO hivatkozik egy oszlopnévre, és egy ugyanolyan nevű lokális vátozóra, a MySQL a változó értékekén veszi figyelembe.
20 DECLARE a változókra DECLARE condition_name CONDITION FOR condition_value condition_value: SQLSTATE [VALUE] sqlstate_value | mysql_error_code A DECLARE...CONDITION utasítás egy nevezett hibát definiál. Részletezi azon feltételeket, amelyek különleges bánásmódot kívánnak és megnevezi ezen feltételket. A nevet hasznáhatjuk egy DECLARE...CONDITION al- szekvenciában. A condition_value lehet egy SQLSTATE érték (5 literál karater szting) vagy egy MySQL error kód. Ne használjuk a ‘00000’ értéket vagy a 0 kódot, mert az pont az ellenkezője.
21 DECLARE a handlerekre DECLARE handler_type HANDLER FOR condition_value [, condition_value]... statement handler_type: CONTINUE | EXIT | UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code
22 A DECLARE... HANDLER utasítás olyan handlereket specifikál, amelyik egyenként egy vagy több feltételt kezelnek. Ha egy ezen feltétlekből felbukkan, a hozzá tartozó statement végrehajtódik. Ez lehet egyszerű (pl. SET var_name = value) vagy összetett utasítás, amely BEGIN és END -et használ. Egy CONTINUE handlernél, a kurrens program futása folytatódik a handler utasítás befejezése után. Egy EXIT handler esetén befejeződik a futtatása a BEGIN...END összetett utasításnak, amelyben deklaráltuk a handlert. (Ez igaz akkor is, ha a feltételek egy belső blokkban léptek fel.) Az UNDO handler tipus nem támogatott ebben a verzióban.
23 Ha egy olyan feltétel lép fel, amire nem volt handler deklaráció, az alapértelmezett akció az EXIT. Egy condition_value a DECLARE... HANDLER valamelyik lehet a következőkből: Egy SQLSTATE érték (egy 5-karakteres sztring literál) vagy egy MySQL error kód (egy szám). Nem használható az SQLSTATE '00000' érték vagy a MySQL error kód 0, mivel ezek inkább a sikert jelképezik, mintsem egy hiba feltételt. Egy listát az SQLSTATE értékekről és a MySQL error kódokról megtalálható a “Server Error Codes and Messages” fejezetben. SQLWARNING egy rövidítése az egy olyan SQLSTATE osztálynak, amely '01‘-el kezdődik.
24 NOT FOUND rövidítése azon SQLSTATE osztály értékeinek, amelyek a '02' kóddal kezdődnek. Ez csak abban az esetben releváns, ha kurzoraink vannak és akkor használjuk, mikor egy kurzor eléri az adathalmaz végét. Ha már nincs több elérhető sor, a No Data feltétel teljesül, amelynek az SQLSTATE értéke Hogy észleljük ezt a feltételt, be lehet állítani egy handlert (vagy egy NOT FOUND feltételnek). Egy példát láthatunk a “Cursors” fejezeben. Ez a feltétel megjelenik egy SELECT... INTO var_list utasításban amelyik nem ad vissza egy sort sem. SQLEXCEPTION egy rövdítése azon SQLSTATE osztály értékeinek, amelyek nem kezdődnek '00', '01', vagy '02' –vel.
25 CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1)); delimiter // CREATE PROCEDURE handlerdemo () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' = 1; = 1; INSERT INTO test.t VALUES (1); = 2; INSERT INTO test.t VALUES (1); = 3; END; // delimiter; CALL handlerdemo();
26 CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; retry: REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN ITERATE retry; # illegal END; IF i < 0 THEN LEAVE retry; # legal END IF; SET i = i - 1; UNTIL FALSE END REPEAT; END;
27 delimiter // CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; DECLARE done INT DEFAULT FALSE; retry: REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN SET done=TRUE; END; IF NOT done AND i<0 THEN LEAVE retry; END IF; SET i=i-1; UNTIL FALSE END REPEAT; END; // delimiter;
28 Bibliográfia red-programs-views.htmlhttp://dev.mysql.com/doc/refman/5.1/en/sto red-programs-views.html