9.GYAKORLAT (ADATBÁZISOK)
   
   Témakör: Oracle PL/SQL témakör első gyakorlatán az ún. "Eljut feladatra" 
   gráfos adatok lekérdezését PL/SQL programmal is megvalósítjuk. Ehhez:
   Először a PL/SQL alapokat tekinjük át (változók, vezérlési szerk., ciklusok,
   DML utasítások, egy sort visszaadó SELECT INTO használata programban. 
   Viszont a több sort visszaadó SELECT-re a kurzorok használatát köv.órán, 
   a PL/SQL haladó témaköreit pedig majd két hét múlva tanuljuk, lépésenként.
   
   A MAI ÓRÁN ELSŐSORBAN A REKURZÍV "ELJUT-FELADATTAL" FOGLALKOZUNK!   
   
   > Eljut feladat: REL5.pdf (9.ea: Datalog), SQL5.pdf (10.ea végén: Rekurzió)
   > Erről rövid összefoglaló a gyakorlatra: Datalog.pdf
   
   > Emlékeztető az Oracle PL/SQL-ről AB1EA : SQL4.pdf (8.előadás)
   > Oracle PL/SQL: Oracle Junior EA >> Oracle PL/SQL.pdf 
   > Oracle PL/SQL segédanyagok: ebben az eduPLSQL mappában  
      -- Tankönyvtár: PL/SQL programozás Oracle 10g-ben (Gábor A.-Juhász I.)
   > Oracle PL/SQL doksi: Oracle 11gR2 doc PL/SQL Language Reference
   
  -- -- --  --
    1.rész: PL/SQL alapjai, PL/SQL blokk szerkezete >> 2.fej. Alapok
      [1_deklarációs_rész] 2_végrehajtható_rész [3_kivételkezelő_rész]
      SET SERVEROUTPUT ON;
      >> példa-2-24 deklarációk-és-értékadás
      >> példa-2-25 select-into (itt a 2-25 példában blokk: begin ... end; /
            át kell tenni az end;-et a végére!) SELECT INTO-t akkor használjuk,
            ha a lekérdezés pontosan egy sort ad, ha a lekérdezés több sorral
            tér vissza, akkor  kurzort kell használni, lásd köv.gyakorlat anyagát).
      >> példa6-1 DML utasítások a programban, implicit kurzor
      >> példa-6-4 implicit kurzor attribútumok
   
   > FELADATSOR 5/A --- PL/SQL--1 feladatok:
     -- A feladatokat most is a saját Dolgozo-Osztaly táblákra kell megírni, ehhez
         a táblákat létrehozó script, mint a DML-hez volt: createDolg (no constraint)
     -- A PL/SQL blokk előtt minden alkalommal állítsuk be: SET SERVEROUTPUT ON
     1.) Az első feladat: Írjuk ki PL/SQL blokkból: 'Szia Világ!', majd egészítsük ki,
          kérjen be egy nevet, számot, dátumot és ezeket is írassuk ki a programból!
     2.) Írjuk ki KING fizetését (olvasás táblából változóba), abban az esetben,
          ha ismert, hogy pontosan egy KING nevű dolgozó szerepel a táblában,
          lásd példa-2-25 select-into (csak ha a lekérdezés pontosan egy sort ad).
     3.) Adjuk meg egy főnök azonosítóját, és töröljük a közvetlen beosztottjait, és
          írassuk ki hány beosztottja volt, lásd  példa-6-4 implicit kurzor attribútumok. 
     
  -- -- --  --
      2.rész:  Vezérlési szerkezetek a PL/SQL-ben 4.fej. Control Statements
      PL/SQL alapjaihoz kiegészítés: Alprogramok (tárolt eljárások/függvények)
      >> példa2-19 Alprogramok (már itt is vannak: 2.fej. Alapok)
      >> példa4-1 Alprogramok IF-THEN utasítás példában (4.fej. Utasítások)
      Vezérlési szerkezetek: Feltételes utasítások, ciklusok
      >> példa-4-5 if-then-elsif utasítás,
      >> példa-4-6 egyszerű case utasítás, és itt írjuk át grade := 'B' -> '&B'
            helyettesítési változóra, aminek a felhasználó adja meg az értékét!
      >> példa-4-10 alap LOOP ciklus utasítás EXIT WHEN kilépés a ciklusból
      >> példa 4-14 FOR ciklus utasítás
      >> példa 4-27 WHILE ciklus utasítás
  -- -- --  --    
      >> Oracle PL/SQL.pdf (és összefoglalók) plsql_01_bevezetes.pdf,
           02_vezerlo_utasitasok.txt02_tipusok.pdf03_dml.pdf05_valtozok.pdf
      --- Ez volt az előkészítés az Eljut feladat megoldásához, lásd köv.3/6.részt.
    
  -- -- --  --
      3.rész:  Az "Eljut feladat" megvalósítása Oracle SQL-ben és PL/SQL-ben
    -- REL5.pdf (9.előadás: Datalog), SQL5.pdf (10.előadás végén: Rekurzió) 
    -- Az Eljut-feladat a Tankönyv (Ullman-Widom kék könyv) 10.2 szakaszára épül
    -- Adott Jaratok(legitarsasag, honnan, hova, koltseg, indulas, erkezes) táblában
        repülőjáratok adatait tároljuk (honnan-hova várospárok). Azt keressük, hogy
        Dallasból mely városokba tudunk eljutni (közvetlenül vagy egy/több átszállással). 
     
      3A.rész:  Az "Eljut feladat" megvalósítása Datalogban és Oracle SQL-ben
    -- Datalogról és az Oracle SQL-ben a with-ről röviden a gyakorlatra: Datalog.pdf

   >> 3.3.1. Az Ullman-Widom Tankönyv szerint (SQL szabvány szerint, csak papíron)
        (konkrét adatbázis-kezelő rendszerekben eltérő megvalósítások lehetnek)  
   
            WITH RECURSIVE eljut(honnan, hova) AS
                  (SELECT honnan, hova FROM jaratok
             UNION
                  SELECT eljut.honnan, jaratok.hova
                  FROM eljut, jaratok
                  WHERE eljut.hova = jaratok.honnan)
            SELECT hova FROM eljut WHERE honnan='DAL';
   
         --- Kérdés: itt miért fontos kiemelni az UNION (halmaz) és
                           UNION ALL (multihalmaz) közötti különbséget?
     
   >> 3.3.2. Az Eljut feladat gépes megvalósítása Oracle-ben:
     -- Ezzel a scripttel jaratok_tabla.txt készítsünk saját táblát.
 
    Ha megfigyeljük a járatok táblában, hogy honnan hova tudunk eljutni és
    ezt felrajzoljuk az első hét soránál nincs kör, ha az utolsó sort elhagyjuk,
    azzal egy olyan jaratok_fa táblát készíthetünk, amelyben nincs kör:
    --- Előkészítés jaratok helyett jaratok_fa egyszerűbb adatokra:
   
   drop table jaratok_fa;
   create table jaratok_fa as
   (select * from jaratok
    fetch first 7 rows only);  --- FIGYELEM! FETCH FIRST Oracle 12c ÚJDONSÁG !
   select * from jaratok_fa;
 
   --- Erre a jaratok_fa táblára az alábbi kódrészlet hibátlanul lefut:
   --- with utasítás az Oracle-ben hierarchikus fa-struktúrájú táblákra:

   WITH eljut(honnan, hova) AS
       (SELECT honnan, hova FROM jaratok_fa jaratok
         UNION ALL
      SELECT jaratok.honnan, eljut.hova
      FROM jaratok_fa jaratok, eljut
      WHERE jaratok.hova = eljut.honnan AND jaratok.honnan <> eljut.hova
      )
    SELECT DISTINCT honnan, hova FROM eljut ORDER BY honnan;
   
   --- Ez a fenti utasítás rendben lefut az Oracle-ben, a szabványhoz képest
       az eltérések, hogy WITH RECURSIVE helyett az Oracle-ben csak WITH,  
       és a UNION az Oracle-ben nem megy, hanem csak UNION ALL működik
   
  --- Viszont ha a fenti WITH utasítást az eredeti jaratok táblára alkalmazzuk,
      ahol a városok közötti utak kört is tartalmazta (nem fa-struktúrájú gráf)
   
   WITH eljut(honnan, hova) AS
       (SELECT honnan, hova FROM jaratok
         UNION ALL
     SELECT jaratok.honnan, eljut.hova
     FROM jaratok, eljut
     WHERE jaratok.hova = eljut.honnan AND jaratok.honnan <> eljut.hova
     )
   SELECT DISTINCT honnan, hova FROM eljut ORDER BY honnan;
   --- ami hibát ad: "ORA-32044: A rekurzív WITH lekérdezésben ciklus van."
       32044. 00000 -  "cycle detected while executing recursive WITH query"
       és csak az alábbi kiegészítéssel működik, Oracle 11gR2 megoldás:
   
            with eljut (honnan, hova) as
                   (select honnan, hova from jaratok
               union all
                    select jaratok.honnan, eljut.hova
                    from jaratok, eljut
                    where jaratok.hova=eljut.honnan
                    )
                SEARCH DEPTH FIRST BY honnan SET SORTING
                CYCLE honnan SET is_cycle TO 1 DEFAULT 0
            select distinct honnan, hova from eljut order by honnan;
     
     -- Példák az Oracle SQL Language Reference 11.2.pdf dokumentációban:
         >> Rekurzió with-utasítással: Recursive Subquery Factoring: Examples
   
  >> 3.3.3. Hierarchikus lekérdezésekre Oracle megoldás (8.ea.pdf legvégén)
   > SQL Lang.Ref: Hierarchical QueriesHierarchical Query Examples
      SELECT ... FROM... WHERE ... START WITH ... CONNECT BY PRIOR ...
       
  -- -- --  --
      3B.rész:  Az "Eljut feladat" megvalósítása Oracle PL/SQL-ben
  >> 3.3.4. Nézzük meg hogyan tudjuk a rekurziót PL/SQL-ben megvalósítani:

   > Rek1.feladat: Mely (x, y) várospárokra lehetséges egy vagy több átszállással
      eljutni x városból y városba? -- Ehhez készítsünk egy Eljut(honnan, hova) táblát, 
      a sorait a járatok tábla alapján PL/SQL programmal töltsük fel (ciklust szervezni, 
      az insert 2.alakja: több sor felvitele alkérdéssel/járatok és eljut táblák alapján).
      >>> (csak ha kell, egy kis segítség, további ötletek és a megoldás vázlata: itt)

   > Rek2.feladat: Mely (x,y) város párokra hány átszállással és milyen költségekkel
      lehetséges egy vagy több átszállással eljutni x városból y városba? -- Ehhez is
      készítsünk Eljut2(honnan, hova, atszallas, koltseg) táblát, a sorait programmal.
    >> Papíron megoldandó feladat: Fejezzük ki az SQL-1999-es szabvány SELECT
         WITH RECURSIVE utasítással, hogy mely mely városokba (hova) tudunk eljutni
         'DAL' (Dallas)-ból legfeljebb 3 átszállással és legfeljebb 5000 költségből.
          >>> (csak ha kell, egy kis segítség WITH RECURSIVE papíros részéhez itt)
      
   > Rek3.feladat: Tegyük fel, hogy nemcsak az érdekel, hogy el tudunk-e jutni az
      egyik városból a másikba, hanem az is, hogy utazásunk során az átszállások is
      ésszerűek legyenek, ez azt jelenti, hogy ha több járattal utazunk, akkor nézni
      kell átszálláskor az érkező járatnak legalább egy órával a rákövetkező indulás
      előtt meg kell érkeznie. (Tegyük fel, hogy nincs egy napnál hosszabb utazás!)
     
   > Rek4.feladat: A fenti feladatokat oldjuk meg PL/SQL-ben úgy is, hogy ne csak
      a várospárokat, hanem a teljes útvonalat is listázzuk ki.
     
 -- -- --
 Ţovábbi gyakorló feladatok az Oracle Példatárból
   > Önálló gyakorlás: Oracle Példatár Feladatok.pdf 8.fejezet 8.1-8.9.feladatok
   > és célszerű készülni a következő gyakorlatra is átnézni: feladat9_plsql.txt