datubaze.files.wordpress.com · web viewkursora izteiksme. kursora izteiksme, ko norāda cursor...
TRANSCRIPT
1
Kursora izteiksme
Kursora izteiksme, ko norāda CURSOR operators, atgriež ligzdotu (nested) kursoru no vaicājuma. Katra rinda ligzdota kursora rezultātu kopā var saturēt parasto vērtību diapazonu, kas atļauts SQL vaicājumā. Tā var saturēt arī citus kursorus, kas izveidoti ar apakšvaicājumiem.
Kursora izteiksmes izmanto, lai atgrieztu lielu un sarežģītu saistīto vērtību kopu, kas izgūta no vienas vai vairākām tabulām. Pēc tam var apstrādāt kursora izteiksmes rezultātu kopu, izmantojot ligzdotās cilpas (nested loops), kas tiek ienestas no rezultātu kopas rindām, un pēc tam papildu rindas no visiem ligzdotajiem kursoriem šajās rindās. Kursora izteiksmes var būt sarežģītas, ņemot vērā, cik sarežģītas var būt vaicājumu un rezultātu kopas. Tomēr ir labi zināt visus iespējamos veidus, kā izgūt datus no Oracle datu bāzes. Kursora izteiksmes var izmantot jebkurā no šīm darbībām:
1) tiešās (explicit) kursora deklarācijās;2) dinamiskos SQL vaicājumos;3) REF CURSOR deklarācijās un mainīgajos.
Nedrīkst izmantot kursora izteiksmi netiešā vaicājumā. Kursora izteiksmes sintakse ir ļoti vienkārša:
CURSOR (apakšvaicājums)
Datu bāze atver ligzdotu kursoru, kas definēts ar kursora izteiksmi, tiklīdz tas no vecākobjekta vai ārējā kursora izgūst rindu, kurā ir kursora izteiksme. Šis ligzdotais kursors ir aizvērts, ja:
1) jūs tieši aizverat kursoru;2) ārējais (augstākstāvošais) kursors tiek izpildīts vēlreiz, aizvērts vai
atcelts;3) ievešanas laikā no vecākkursora tiek pacelts izņēmums. Ligzdotais
kursors tiek aizvērts kopā ar augstākstāvošo kursoru.
2
Tabulu FAKULTATES un STUDENTI izveidošana
create table FAKULTATES (F_NUM number Primary key,F_NOS varchar2(20));
begininsert into FAKULTATES values (1, 'Datorzinības');insert into FAKULTATES values (2, 'Elektronika');end;
create table STUDENTI (S_NUM number Primary key,UZV varchar2(20),KURSS number,NUM_F number);
begininsert into STUDENTI values (1001, 'Koks', 3, 1 );insert into STUDENTI values (1002, 'Celms', 2, 1 );insert into STUDENTI values (1003, 'Sakne', 1, 2 );insert into STUDENTI values (1004, 'Lapa', 3, 2 );end;
select F_NUM, F_NOS, S_NUM, UZV from FAKULTATES, STUDENTIwhere NUM_F = F_NUM;
3
Apakšvaicājuma veidošana ar kursora izteiksmi
Kursora izteiksmes lietošana ir atļauta tikai augšējā SELECT līmenī!
select F_NUM, F_NOS, CURSOR (select S_NUM, UZV from STUDENTI where NUM_F = F_NUM) STUD_KURSORSfrom FAKULTATES;
select CURSOR(select S_NUM, UZV from STUDENTI where F_NUM =NUM_F) FAK_STUDfrom FAKULTATES;
4
Kursorā iekļauta kursora izteiksme CURSOR() un tabulas kolona
Tiek izmantots kursors ar kursora izteiksmi un kursora mainīgais. Izgūšanā tiek izmantoti divi cikli:1) kursora datu izgūšana (F_NOS). Tiek izmantots kursora mehānisms.2) kursora izteiksmes datu izgūšana (UZV). Dati tiek izgūti kursora manīgajā.declare type KURS_MAIN_TIPS is REF CURSOR; kurs_main KURS_MAIN_TIPS; --Kursora mainīgā definēšana fak_nos FAKULTATES.F_NOS%type; stud_uzv STUDENTI. UZV%type;-- Kursora ar kursora izteiksmi definēšana cursor KURSORS is select F_NOS, CURSOR ( select UZV from STUDENTI where NUM_F = F_NUM order by UZV ) stud from FAKULTATES;beginopen KURSORS;-- Kursora buferī esošo datu izgūšana (F_NOS + CURSOR())loop fetch KURSORS into fak_nos, kurs_main; exit when KURSORS%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Fakultāte: ' || fak_nos);-- Datu uz ko norāda kursora mainīgais izgūšana loop fetch kurs_main into stud_uzv; exit when kurs_main%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Studenti: ' || stud_uzv); end loop;end loop;close KURSORS; end;
5
Kursora izteiksme atgriež vairākas vērtības rindā
declaretype KURS_MAIN_TIPS is REF CURSOR;kurs_main KURS_MAIN_TIPS; --Kursora mainīgā definēšana fak_nos FAKULTATES.F_NOS%type; stud_num STUDENTI.S_NUM%type; stud_uzv STUDENTI. UZV%type;-- Kursora ar kursora izteiksmi definēšana cursor KURSORS is select F_NOS, CURSOR ( select S_NUM, UZV from STUDENTI where NUM_F = F_NUM order by UZV ) stud from FAKULTATES;beginopen KURSORS;-- Kursora buferī esošo datu izgūšana (F_NOS + CURSOR())loop fetch KURSORS into fak_nos, kurs_main; exit when KURSORS%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Fakultāte: ' || fak_nos);-- Datu uz ko norāda kursora mainīgais izgūšana loop fetch kurs_main into stud_num, stud_uzv; exit when kurs_main%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Studenti: ' || stud_num || ' ' || stud_uzv); end loop;end loop;close KURSORS; end;
6
Tikai kursora izteiksmes CURSOR() iekļaušana kursorā
Tiek izmantots kursors ar kursora izteiksmi un kursora mainīgais.declare type KURS_MAIN_TIPS is REF CURSOR; kurs_main KURS_MAIN_TIPS; --Kursora mainīgā definēšana fak_nos FAKULTATES.F_NOS%type; stud_uzv STUDENTI. UZV%type;-- Kursora ar kursora izteiksmi definēšana cursor KURSORS is select CURSOR ( select UZV from STUDENTI where NUM_F = F_NUM order by UZV ) stud from FAKULTATES;beginopen kursors;-- Kursora buferī esošo datu izgūšana (CURSOR()loop fetch KURSORS into kurs_main; exit when kursors%NOTFOUND;-- DBMS_OUTPUT.PUT_LINE('Fakultāte: ' || fak_nos);-- Datu uz ko norāda kursora mainīgais izgūšana loop fetch kurs_main into stud_uzv; exit when kurs_main%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Studenti: ' || stud_uzv); end loop;end loop;close KURSORS;end;
7
Kursora izteiksmes izmantošanas veidi
Kursa izteiksmi var izmantot divos dažādos, bet ļoti noderīgos veidos: 1) apakšvaicājuma izgūšanai kā kolonnu ārējā vaicājumā;2) lai pārvērstu vaicājumu par rezultātu kopu, ko var nodot kā
argumentu straumēšanas vai transformācijas funkcijai.
8
Apakšvaicājuma izgūšana kā kolonna
Šī procedūra parāda ligzdotu CURSOR izteiksmju izmantošanu, lai izgūtu apakšvaicājumu kā kolonnu ārējā vaicājumā. Augšējā līmeņa vaicājums ienes tikai divus datus: pilsētas atrašanās vietu un ligzdotu kursoru, kurā ir šīs pilsētas nodaļas. Šis ligzdotais kursors savukārt ienes ligzdotu kursoru ar CURSOR izteiksmi - šajā gadījumā ar visu nodaļu darbinieku vārdiem. Es būtu varējis veikt šo pašu izguvi ar atsevišķiem tiešiem kursoriem, atvērt un apstrādāt ligzdotā veidā. CURSOR izteiksme sniedz mums iespēju izmantot atšķirīgu pieeju, kas var būt daudz kodolīgāka un efektīvāka, ņemot vērā, ka visa apstrāde notiek SQL priekšraksta izpildītājā (kas samazina konteksta pārslēgšanos).
9
PROCEDURE emp_report (p_locid NUMBER) IS TYPE refcursor IS REF CURSOR; -- The query returns only 2 columns, but the second column is -- a cursor that lets us traverse a set of related information. CURSOR all_in_one_cur is SELECT l.city, CURSOR (SELECT d.department_name, CURSOR(SELECT e.last_name FROM employees e WHERE e.department_id = d.department_id) AS ename FROM departments d WHERE l.location_id = d.location_id) AS dname FROM locations l WHERE l.location_id = p_locid;departments_cur refcursor; employees_cur refcursor; v_city locations.city%TYPE; v_dname departments.department_name%TYPE; v_ename employees.last_name%TYPE; BEGIN OPEN all_in_one_cur; LOOP FETCH all_in_one_cur INTO v_city, departments_cur; EXIT WHEN all_in_one_cur%NOTFOUND; -- Now I can loop through departments and I do NOT need to -- explicitly open that cursor. Oracle did it for me. LOOP FETCH departments_cur INTO v_dname, employees_cur; EXIT WHEN departments_cur%NOTFOUND;-- Now I can loop through employees for that department. -- Again, I do not need to open the cursor explicitly. LOOP FETCH employees_cur INTO v_ename; EXIT WHEN employees_cur%NOTFOUND; DBMS_OUTPUT.put_line (v_city || ' ' || v_dname || ' ' || v_ename ); END LOOP; END LOOP; END LOOP; CLOSE all_in_one_cur; END;
10
Straumēšanas (straming) funkcijas ieviešana ar KURSORA izteiksmēm
Straumēšanas funkcijām, ko sauc arī par transformējošām funkcijām, ļauj pārveidot datus no viena stāvokļa uz citu, neizmantojot lokālās datu struktūras kā starppieturvietas. Pieņemsim, ka, piemēram, man ir jāņem dati StockTable un jāpārvieto tie TickerTable, StockTable pārgriežot vienu rindu uz divām TickerTable rindām. Izmantojot CURSOR izteiksmi un galda funkcijas, šo risinājumu varu ieviest šādi:
Izplatīts tabulu funkciju lietojums ir datu straumēšana tieši no viena procesa vai transformācijas uz nākamo procesu, bez starpposma. Šādā veidā izmantotā tabulas funkcija tiek saukta par straumēšanas tabulas funkciju.
insert into MERKA_TABULA SELECT * from TABLE (TRANFORM_FUNKCIJAt (CURSOR (SELECT * from AVOTA_TABULA)))
1. Paņem visus datus no stocktable....2. Pārvērst to par kursora mainīgo ar CURSOR izteiksmi...3. Nodot šo kursora mainīgo stockpivot tabulas funkcijai...4. Funkcija atgriež ligzdtabulu ar objekta tipa instancēm...5. TABLE operators konvertē šo kolekciju relāciju tabulas formātā...6. SELECT visas rindas no pseidotabulas...7. INSERT tās jaunajā tabulā.Un, kā norāda attēls, var veikt vairākas transformācijas, kā parādīts:
11
And as the image indicates, you can perform multiple transformations, as in:
INSERT INTO ticker tableSELECT * FROM TABLE (ticker pivot ( CURSOR (SELECT * FROM TABLE(stockpivot ( CURSOR (SELECT * FROM stocktable))))))
12
Kursora izteiksmes ierobežojumi
Ir virkne ierobežojumu, kas ierobežo kursora izteiksmju izmantošanu:1) nedrīkst izmantot kursora izteiksmi ar netiešu kursoru, jo nav
pieejams mehānisms, lai ienestu ligzdotu kursoru PL/SQL datu struktūrā;
2) kursa izteiksmes var parādīties tikai vaicājuma SELECT specifikācijas tālākajā atlases sarakstā;
3) kursa izteiksmes var novietot tikai SELECT priekšrakstā, kas nav ligzdots nevienā citā vaicājuma izteiksmē, izņemot gadījumus, kad tā IR definēta kā rokraksta izteiksme, kad jūs nevarat izpildīt kursora izteiksmes apakšvaicājumu.
4) veidojot skatu, nevar izmantot kursora izteiksmes;5) izmantojot kursora izteiksmi dināmiskajā SQL, nevar veikt
BINDun EXECUTE operācijas ar CURSOR izteiksmēm
13
Cursor Variables as Subprogram Parameters
You can use a cursor variable as a subprogram parameter, which makes it useful for passing query results between subprograms.For example: You can open a cursor variable in one subprogram and process it in a different subprogram. In a multilanguage application, a PL/SQL subprogram can use a cursor variable to return a result set to a subprogram written in a different language.Note:The invoking and invoked subprograms must be in the same database instance. You cannot pass or return cursor variables to subprograms invoked through database links.Caution:Because cursor variables are pointers, using them as subprogram parameters increases the likelihood of subprogram parameter aliasing, which can have unintended results. When declaring a cursor variable as the formal parameter of a subprogram: If the subprogram opens or assigns a value to the cursor variable, then the parameter mode must be IN OUT. If the subprogram only fetches from, or closes, the cursor variable, then the parameter mode can be either IN or IN OUT. Corresponding formal and actual cursor variable parameters must have compatible return types. Otherwise, PL/SQL raises the predefined exception ROWTYPE_MISMATCH. To pass a cursor variable parameter between subprograms in different PL/SQL units, define the REF CURSOR type of the parameter in a package. When the type is in a package, multiple subprograms can use it. One subprogram can declare a formal parameter of that type, and other subprograms can declare variables of that type and pass them to the first subprogram.
14
Apakšprogrammas parametru pieņemtie vārdi (aliasing) ar kursora mainīgajiem parametriem
Kursora mainīgie parametri ir rādītāji (pointers). Tāpēc, ja apakšprogramma piešķir vienu kursora mainīgā parametru citam, tie attiecas uz to pašu atmiņas atrašanās vietu. Šai aliasing var būt neparedzēti rezultāti.Piemērā procedūrai ir divi kursora mainīgie parametri - emp_cv1 un emp_cv2. Procedūra atver emp_cv1 un piešķir emp_cv2 tās vērtību (kas ir rādītājs). Tagad emp_cv1 un emp_cv2 attiecas uz vienu un to pašu vietu atmiņā. Kad procedūra aizver emp_cv1, tā aizver arī emp_cv2. Tāpēc, mēģinot veikt procedūru no emp_cv2, PL/SQL rada īpašo situāciju.
DECLARE TYPE EmpCurTyp IS REF CURSOR; c1 EmpCurTyp; c2 EmpCurTyp;PROCEDURE get_emp_data (emp_cv1 IN OUT EmpCurTyp,emp_cv2 IN OUT EmpCurTyp ) IS emp_recemployees%ROWTYPE; BEGIN OPEN emp_cv1 FOR SELECT * FROM employees; emp_cv2 := emp_cv1; -- now both variables refer to same location FETCH emp_cv1 INTO emp_rec; -- fetches first row of employees FETCH emp_cv1 INTO emp_rec; -- fetches second row of employees FETCH emp_cv2 INTO emp_rec; -- fetches third row of employees CLOSE emp_cv1; -- closes both variables FETCH emp_cv2 INTO emp_rec; -- causes error when get_emp_data is invoked END;
BEGIN
15
get_emp_data(c1, c2);END;Result:DECLARE*ERROR at line 1:ORA-01001: invalid cursorORA-06512: at line 19ORA-06512: at line 22