Cviceni 7
--
-- vytvoreni a naplneni tabulek pro vazbu mezi uciteli a predmety
--
SQL> DROP TABLE ucitele;
SQL> CREATE TABLE ucitele (id NUMBER PRIMARY KEY, jmeno VARCHAR2(20));
SQL> INSERT INTO ucitele VALUES (1,'Matyas');
SQL> INSERT INTO ucitele VALUES (2,'Riha');
SQL> INSERT INTO ucitele VALUES (3,'Svenda');

SQL> DROP TABLE predmety;
SQL> CREATE TABLE predmety (id NUMBER PRIMARY KEY, jmeno VARCHAR2(20));
SQL> INSERT INTO predmety VALUES (1,'Architektura RDBS');
SQL> INSERT INTO predmety VALUES (2,'Projekt z DBS');
SQL> INSERT INTO predmety VALUES (3,'Autentizace');
SQL> INSERT INTO predmety VALUES (4,'Zonglovani');

SQL> DROP TABLE uci;
SQL> CREATE TABLE uci (kdo NUMBER, co NUMBER);
SQL> INSERT INTO uci VALUES (2,1);
SQL> INSERT INTO uci VALUES (2,3);
SQL> INSERT INTO uci VALUES (1,3);

SQL> DROP TABLE logs;
SQL> CREATE TABLE logs(logline VARCHAR2(50));

...
Table created.
1 row created.
...

--
-- kursor, ktery nacte bez pozuiti cyklu prvni tri zaznamy a ulozi od specialni tabulky
-- 
SQL> DROP TABLE ucitele_jmena;
SQL> CREATE TABLE ucitele_jmena (jmeno VARCHAR2(20));
SQL> 
DECLARE
CURSOR pr1 IS SELECT jmeno FROM ucitele;
name1 ucitele.jmeno%TYPE;
name2 ucitele.jmeno%TYPE;
name3 ucitele.jmeno%TYPE;
BEGIN
OPEN pr1;
FETCH pr1 INTO name1; -- ziskam prvni radek
FETCH pr1 INTO name2; -- ziskam druhy radek
FETCH pr1 INTO name3; -- ziskam treti radek

INSERT INTO ucitele_jmena VALUES (name1);
INSERT INTO ucitele_jmena VALUES (name2);
INSERT INTO ucitele_jmena VALUES (name3);

CLOSE pr1;
END;
/
PL/SQL procedure successfully completed.

SQL> SELECT * FROM ucitele_jmena; 

JMENO
--------------------
Matyas
Riha
Svenda

--
-- kurzor se vstupnimi parametry 
-- pouziti attributu %NOTFOUND pro ukonceni nekonecneho cyklu nacitani (kdyz neni nalezen dalsi zaznam)
-- pouziti attributu %ISOPEN pro detekci stavu kurzoru
SQL> DELETE FROM ucitele_jmena;

3 rows deleted.

SQL>
DECLARE
CURSOR pr2(id_low NUMBER, id_high NUMBER) IS SELECT jmeno FROM ucitele WHERE ucitele.id BETWEEN id_low AND id_high;
name ucitele.jmeno%TYPE;

BEGIN
OPEN pr2(1, 2); -- parametry se zadavaji pri otevreni kurzoru
IF pr2%ISOPEN THEN INSERT INTO logs(logline) VALUES ('pr2 je otevren'); END IF;
LOOP
    FETCH pr2 INTO name;  
    EXIT WHEN pr2%NOTFOUND;
    INSERT INTO ucitele_jmena VALUES (name);
END LOOP;
CLOSE pr2;

IF NOT pr2%ISOPEN THEN INSERT INTO logs(logline) VALUES ('pr2 je uz uzavren'); END IF;

END;
/

PL/SQL procedure successfully completed.

SQL> SELECT * FROM ucitele_jmena; 

JMENO
--------------------
Matyas
Riha

SQL> SELECT * FROM logs;

LOGLINE
--------------------------------------------------
pr2 je otevren
pr2 je uz uzavren

--
-- funkce vyuzivajici kurzor na zjisteni poctu predmetu, ktere vyucuje ucitel se zadanym id 
--
SQL> 
CREATE OR REPLACE FUNCTION pocet_uci(id NUMBER) RETURN NUMBER AS 
  CURSOR pr3 IS SELECT * FROM uci;
  pocet_predmetu NUMBER := 0;
  BEGIN
  FOR uci_rec IN pr3    -- FOR cyklus nacita do promenne typu %ROWTYPE
  LOOP
    IF uci_rec.kdo = id THEN pocet_predmetu := pocet_predmetu + 1;
    END IF;
  END LOOP;
  
  RETURN pocet_predmetu;
END;
/

Function created.

SQL> SHOW ERROR;
SQL> SELECT pocet_uci(2) AS FROM dual;

POCET_UCI(2)
------------
           2

--
-- vyuziti hromadneho nacteni vsech zaznamu z tabulky pomoci BULK COLLECT
-- vyuziti %ROWCOUNT pro explicitni kurzor
--
SQL> 
DECLARE
TYPE jmenoTab IS TABLE OF ucitele.jmeno%TYPE;   -- definice typu vysledne tabulky  
names jmenoTab;
pocet NUMBER;
CURSOR pr4 IS SELECT jmeno FROM ucitele; 
BEGIN
OPEN pr4;
FETCH pr4 BULK COLLECT INTO names;    -- hromadne nacteni jmen

-- rozhodovani dle poctu nactenych zaznamu pomoci attributu %ROWCOUNT
IF (pr4%ROWCOUNT > 2) THEN
    -- pouze ulozeni hlaseni, ze bylo nacteno prilis mnoho zaznamu 
    pocet := pr4%ROWCOUNT;
    INSERT INTO ucitele_jmena(jmeno) VALUES ('moc ucitelu:' || TO_CHAR(pocet));
ELSE
    -- ulozeni nactenych dat do tabulky
    FORALL i IN names.first .. names.last INSERT INTO ucitele_jmena(jmeno) VALUES (names(i));
END IF;    

CLOSE pr4;
END;
/

PL/SQL procedure successfully completed.

SQL> SHOW ERROR;
SQL> SELECT * FROM ucitele_jmena;

JMENO
--------------------
Matyas
Riha
moc ucitelu:3

SQL> SELECT COUNT(*) Pocet_ucitelu FROM ucitele_jmena;

POCET_UCITELU
-------------
            3

-- implicitni kursor po operaci DELETE
SQL> 
DECLARE
pocet NUMBER;    
u_jmeno CONSTANT VARCHAR2(20) := 'Neexistujici';
BEGIN
    DELETE FROM ucitele_jmena WHERE jmeno = u_jmeno;
    IF (SQL%FOUND) THEN
        INSERT INTO logs(logline) VALUES ('ucitel ' || u_jmeno || ' smazan');
    ELSE 
        INSERT INTO logs(logline) VALUES ('ucitel ' || u_jmeno || ' nebyl nalezen');
    END IF;
    
    DELETE FROM ucitele_jmena; 
    pocet := SQL%ROWCOUNT;
    INSERT INTO logs(logline) VALUES ('Celkem smazano ' || TO_CHAR(pocet) || ' ucitelu'); 
END;
/

PL/SQL procedure successfully completed.

SQL> SHOW ERROR;
SQL> SELECT * FROM logs;

LOGLINE
--------------------------------------------------
pr2 je otevren
pr2 je uz uzavren
ucitel Neexistujici nebyl nalezen
Celkem smazano 3 ucitelu