2.5. PL/SQL

2.5.1. PL/SQL blokk feladatok

2.5.1.1. Ismertesse a PL/SQL blokk általános szerkezetét!

   [declare
      Konstansok
      Változók
      Kurzor
      Kivétel
   ]
   begin
       pl/sql utasítások
   [ exception kezelés]
   end;

2.5.1.2. Írjon egy oylan PL/SQL programot ami kiírja a kimenetre hogy "Hello World"!

   begin
       dbms_output.put_line('hello world');
   end;

2.5.1.3. Írjon egy olyan PL/SQL programot amely összead két számot és kiírja a kimenetre!

   DECLARE
      s number;
   BEGIN
      s := (5+3);
      dbms_output.put_line(TO_CHAR(s));
   END;

2.5.1.4. Írjon egy olyan PL/SQL programot amely összeszoroz két számot és kiírja a kimenetre!

   declare
      a number default 10;
      b number default 20;
      s number;
   begin
      s:= a*b;
      dbms_output.put_line(TO_CHAR(s));
   end;

2.5.1.5. Írjon egy olyan PL/SQL programot amely kiírja a "Hello World" szöveget csupa nagy illetve kis betűkkel a kimenetére!

   declare
      t VARCHAR(20) := 'Hello World';
   begin
      SELECT UPPER(t) INTO t FROM dual;
      dbms_output.put_line((t));
   
      SELECT LOWER(t) INTO t FROM dual;
      dbms_output.put_line((t));
   
      SELECT INITCAP(t) INTO t FROM dual;
      dbms_output.put_line((t));
   end;                

2.5.1.6. Írjon egy olyan PL/SQL programot amely összefűzve kiírja a kimenetére a "Hello " és a "World" string-eket!

   DECLARE
      t1 VARCHAR(10) := 'Hello ';
      t2 VARCHAR(10) := 'World!';
      t VARCHAR(20) := '';
   BEGIN
      SELECT CONCAT(t1,t2) INTO t FROM dual;
      dbms_output.put_line(t);
   END;

2.5.1.7. Írjon egy olyan PL/SQL programot amely kiírja az aktuális rendszeridőt!

   DECLARE
      d DATE;
   BEGIN
      SELECT sysdate INTO d FROM dual;
      dbms_output.put_line(d);
   END;

2.5.1.8. Írjon egy olyan PL/SQL programot amely kiírja a rendszeridőt 'YYYY-MM-DD' formátumban!

   DECLARE
      t VARCHAR(30);
   BEGIN
      SELECT TO_DATE(SYSDATE,'YYYY-MM-DD')INTO t FROM dual;
      dbms_output.put_line(t);
   
      SELECT TO_DATE(SYSDATE,'DD-MM-YYYY')INTO t FROM dual;
      dbms_output.put_line(t);
   END;

2.5.1.9. Írjon egy olyan PL/SQL programot amely lekérdezi a vásárlók neveit és letárolja a megfelelő típusba %type segítségével!

   DECLARE
      name vasarlo.nev%type;
   BEGIN
      SELECT nev INTO name FROM vasarlo WHERE id = 11;
      dbms_output.put_line(name);
   END;

2.5.1.10. Írjon egy olyan PL/SQL programot amely lekérdezi egy vásárló adatait és letárolja az adatokat a megfelelő %type típusú változókba!

   DECLARE
      id vasarlo.id%type;
      name vasarlo.nev%type;
      mail vasarlo.mail%type;
      mobil vasarlo.mobil%type;
      address vasarlo.cim%type;
      aktiv vasarlo.aktiv%type;
   BEGIN
      SELECT id,nev,mail,mobil,cim,aktiv INTO id,name,mail,mobil,address,aktiv FROM vasarlo WHERE id = 11;
      dbms_output.put_line(id|| ' '|| name||' '||mail||' '||mobil||' '||address||' '||aktiv);
   END;

2.5.1.11. Írjon egy olyan PL/SQL programot amely lekérdezi egy adott vásárló rekordot és letárolja egy %rowtype típusú változóba!

   DECLARE
      row vasarlo%rowtype;
   BEGIN
      SELECT * INTO row FROM vasarlo WHERE id = 11;
      dbms_output.put_line(row.id|| ' '|| row.nev||' '||row.mail||' '||row.mobil||' '||row.cim||' '||row.aktiv);
   END;

2.5.2. Vezérlési szerkezet feladatok

2.5.2.1. Ismertesse az IF szerkezetet!

   IF feltetel THEN
      utasitas
   [ ELSIF feltetel THEN
      utasitas]
   [ELSE
      utasitas]
   END IF;

2.5.2.2. Írjon egy olyan PL/SQL programot amely eldönti két szám közül hogy melyik a nagyobb!

   DECLARE
      a number := 10;
      b number := 81;
   BEGIN
      IF a > b THEN
        dbms_output.put_line('Az "a" szam a nagyobb!!!');
      ELSE
        dbms_output.put_line('A "b" szam a nagyobb!!!');
      END IF;
   END;

2.5.2.3. Írjon egy olyan PL/SQL programot amely eldönti egy számról hogy bele esik e két másik szám által megadott intervallumba!

   DECLARE
      minimum number := 10;
      maximum number := 100;
      ertek number := 50;
   BEGIN
      IF ertek < minimum THEN
        dbms_output.put_line('Tul kicsi!!!');
      ELSIF maximum < ertek THEN
        dbms_output.put_line('Tul nagy!!!');
      ELSE
        dbms_output.put_line('OK!!!');
      END IF;
   END;

2.5.2.4. Ismertesse a Swith Case szerkezetet!

   CASE
           WHEN  feltetel THEN utasitasok
           WHEN  feltetel THEN utasitasok
           ...
           ELSE utasitasok
   END CASE;

2.5.2.5. Írjon egy olyan PL/SQL programot amely a beosztás rövidítése alapján megadja, a dolgozó teljes beosztását!

   DECLARE
      beosztas VARCHAR(10) := 'coder';
   BEGIN
     CASE
       WHEN beosztas = 'dev' THEN dbms_output.put_line('Fejleszto, tervezo');
       WHEN beosztas = 'root' THEN dbms_output.put_line('Rendszergazda (UNIX/LINUX)');
       WHEN beosztas = 'admin' THEN dbms_output.put_line('Rendszergazda (Windows)');
       WHEN beosztas = 'dba' THEN dbms_output.put_line('Adatbazis Adminisztrator');
       WHEN beosztas = 'coder' THEN dbms_output.put_line('Programozo');
       WHEN beosztas = 'sec' THEN dbms_output.put_line('Adminisztrativ');
       ELSE dbms_output.put_line('egyedi munkakor');
     END CASE;
   END;

2.5.2.6. Írjon egy olyan PL/SQL programot amely eldönti három számról hogy alkothat e háromszöget!

   DECLARE
     a number := 3;
     b number := 4;
     c number := 5;
   BEGIN
     IF (a > b+c) or (b > a+c) or (c > a+b) THEN
       dbms_output.put_line('A '||a||' '||b||' '||c||' szamharmas nem alkot haromszoget!!!');
     ELSE
       dbms_output.put_line('A '||a||' '||b||' '||c||' szamharmas haromszoget alkot!!!');
     END IF;
   END;

2.5.2.7. Írjon egy olyan PL/SQL programot amely a háromszög három oldala ismeretében kiszámolja a területét a Heron képlet segítségével!

   DECLARE
      a number := 3;
      b number := 4;
      c number := 5;
      s number;
      t number;
   BEGIN
      IF (a > b+c) or (b > a+c) or (c > a+b) THEN
        dbms_output.put_line('A '||a||' '||b||' '||c||' szamharmas nem alkot haromszoget!!!');
      ELSE
        s := (a+b+c)/2;
        t := SQRT(s*(s-a)*(s-b)*(s-c));
        dbms_output.put_line('A '||a||' '||b||' '||c||' szamharmas haromszoget alkot, aminek a terulete '||t||'!!!');
      END IF;
   END;

2.5.2.8. Ismertesse a Loop ciklust PL/SQL-ben!

   LOOP
      utasitasok;
   END LOOP;

2.5.2.9. Ismertesse a While ciklust PL/SQL-ben!

   WHILE feltetel  LOOP
      utasitasok
   END LOOP;

2.5.2.10. Ismertesse a For ciklust PL/SQL-ben!

   FOR i IN lista LOOP
      utasitasok
   END LOOP;

2.5.2.11. Írjon egy olyan PL/SQL programot amely kiírja 1-től n-ig a számokat!

   DECLARE
      n number := 10;
   BEGIN
      FOR i IN 1..n LOOP
        dbms_output.put_line(TO_CHAR(i));
      END LOOP;
   END;

2.5.2.12. Írjon egy olyan PL/SQL programot amely kiírja az első n darab Fibonacci számot!

   DECLARE
      n number := 10;
      f0 number := 0; -- f_{n-2}
      f1 number := 1; -- f_{n-1}
      fa number := 2; -- f_{n}
   BEGIN
      FOR i IN 1..n LOOP
        fa := f0 + f1;
        f0 := f1;
        f1 := fa;
        dbms_output.put_line(TO_CHAR(fa));
      END LOOP;
   END;

2.5.2.13. Írjon egy olyan PL/SQL programot amely eldönti egy n számról hogy prím szám e!

   DECLARE
     n number := 10;
     gyok number;
     gyoke boolean := true;
   BEGIN
     gyok := ROUND(SQRT(n));
     FOR i IN 2..gyok LOOP
       IF (mod(n,i) = 0) and (gyoke = true) THEN
         gyoke := false;
         dbms_output.put_line(n||' oszthato '||i||'-vel');
       END IF;
     END LOOP;
   
     IF gyoke = true THEN
        dbms_output.put_line(n||' prim szam!!!');
     ELSE
        dbms_output.put_line(n||' nem prim szam!!!');
     END IF;
   END;

2.5.3. Hibakezelés feladatok

2.5.3.1. Soroljon fel néhány gyári kivételt a PL/SQL-ben!

   INVALID_CURSOR
   CURSOR_ALREADY_OPEN
   ZERO_DIVIDE

2.5.3.2. Írjon egy olyan PL/SQL programot amely ZERO_DIVIDE kivételt dob!

   BEGIN
      dbms_output.put_line(4/0);
   END;

2.5.3.3. Írjon egy olyan PL/SQL programot amely ZERO_DIVIDE kivételt dob és lekezeli!

   BEGIN
      dbms_output.put_line(4/0);
   EXCEPTION
      WHEN ZERO_DIVIDE THEN
      dbms_output.put_line('0-val nem lehet osztani!!!');
   END;

2.5.3.4. Írjon egy olyan PL/SQL programot amelyben saját kivételt definiál és kezel ( a kivétel akkor keletkezzen ha a szám páros )!

   DECLARE
      n number := 10;
      paros EXCEPTION;
   BEGIN
      FOR i IN  1..n LOOP
        IF mod(i,2) = 0 THEN 
          RAISE paros;
        END IF;
        dbms_output.put_line(i);
      END LOOP;
   EXCEPTION
      WHEN paros THEN
       dbms_output.put_line('paros');
   END;

2.5.3.5. Írjon egy olyan PL/SQL programot amelyben egy CURSOR-t kétszer akar megnyitni és kivétel keletkezik

   DECLARE
      CURSOR c1 IS SELECT * FROM VASARLO;
   BEGIN
     OPEN c1;
     OPEN c1;
   
   EXCEPTION
     WHEN CURSOR_ALREADY_OPEN THEN
      dbms_output.put_line('A CURSOR mar meg van nyitva');
   END;

2.5.4. Lekérdezés feladatok

2.5.4.1. Eredmények tárolása változókban

2.5.4.1.1. Írjon egy olyan PL/SQL programot amelyben a vásárló nevét egy változóba tárolja, adja meg a hiba lehetőségét!
   DECLARE
      name VARCHAR(5);
   BEGIN
      SELECT nev INTO name FROM vasarlo WHERE id = 11;
      dbms_output.put_line(name);
   END;
2.5.4.1.2. Írjon egy olyan PL/SQL programot amely a vásárló nevét tárolja le %type típusú változóba, hasonlítsa össze az előző példával a jelen példát!
   DECLARE
       name vasarlo.nev%type;
   BEGIN
       SELECT nev INTO name FROM vasarlo WHERE id = 11;
        dbms_output.put_line(name);
   END;
2.5.4.1.3. Írjon egy olyan PL/SQL programot amelyben több mezőt is kinyer a %type típusú változókba!
   DECLARE
     id vasarlo.id%type;
     name vasarlo.nev%type;
     mail vasarlo.mail%type;
     mobil vasarlo.mobil%type;
     address vasarlo.cim%type;
     aktiv vasarlo.aktiv%type;
   BEGIN
     SELECT id,nev,mail,mobil,cim,aktiv INTO id,name,mail,mobil,address,aktiv FROM vasarlo WHERE id = 11;
     dbms_output.put_line(id|| ' '|| name||' '||mail||' '||mobil||' '||address||' '||aktiv);
   END;
2.5.4.1.4. Írjon egy olyan PL/SQL programot amelyben a lekérdezés eredményét egy %rowtype változóba tárolja le!
   DECLARE
      row vasarlo%rowtype;
   BEGIN
     SELECT * INTO row FROM vasarlo WHERE id = 11;
     dbms_output.put_line(row.id|| ' '|| row.nev||' '||row.mail||' '||row.mobil||' '||row.cim||' '||row.aktiv);
   END;
2.5.4.1.5. Írjon egy olyan PL/SQL programot amely lekérdezi hogy egy adott vásárló aktív e, vegye észre, hogy a megadott típus nem Boolean és a mezőnek Boolean-t kéne visszaadnia!
   DECLARE
      aktiv VARCHAR(5);
   BEGIN
      SELECT aktiv INTO aktiv FROM vasarlo WHERE id = 11;
      dbms_output.put_line(aktiv);
   END;
2.5.4.1.6. Írjon egy olyan PL/SQL programot amely az előző példát valósítja meg, de az aktív mező szám érétket kap!
   DECLARE
      aktiv NUMBER;
   BEGIN
      SELECT aktiv INTO aktiv FROM vasarlo WHERE id = 11;
      dbms_output.put_line(aktiv);
   END;
2.5.4.1.7. Írjon egy olyan PL/SQL programot amely egyszerre használ %type és más típust egy lekérdezésben!
   DECLARE
      aktiv NUMBER;
      nev vasarlo.nev%type;
   BEGIN
      SELECT aktiv,nev INTO aktiv,nev FROM vasarlo WHERE id = 11;
      dbms_output.put_line(nev||' '||aktiv);
   END;
2.5.4.1.8. Ismertesse a SELECT  szerkezetét a PL/SQL blokkban!
   SELECT mezoneve INTO valtozok listaja FROM ...

2.5.4.2. Kurzorkezelés

2.5.4.2.1. Ismertesse a CURSOR definiálás formalizmusát!
   CURSOR c_nev IS SELECT ...
2.5.4.2.2. Ismertesse a paraméteres CURSOR definiálás formalizmusát!
   CURSOR c_nev(paramterek) IS SELECT ...
2.5.4.2.3. Írjon egy olyan PL/SQL programot amely cursor segítségével lekérdezi a vásárlók tábla adatait!
   declare
      mobil vasarlo.mobil%TYPE;
      cim vasarlo.cim%TYPE;
       cursor cVasarlo is select mobil,cim from vasarlo;
   begin
      open cVasarlo;
      loop
        fetch cVasarlo into mobil,cim;
        dbms_output.put_line('mobil: '||mobil||' cim: '||cim);
        exit when cVasarlo%NOTFOUND;
      end loop;
      close cVasarlo;
   end;
2.5.4.2.4. Írjon egy olyan PL/SQL programot amely lekérdezi az aktív vásárlók adatait!
   declare
      mobil vasarlo.mobil%TYPE;
      cim vasarlo.cim%TYPE;
      cursor cVasarlo is select mobil,cim from vasarlo where aktiv=1;
   begin
      open cVasarlo;
      loop
        fetch cVasarlo into mobil,cim;
        dbms_output.put_line('mobil: '||mobil||' cim: '||cim);
        exit when cVasarlo%NOTFOUND;
      end loop;
      close cVasarlo;
   end;
2.5.4.2.5. Írjon egy olyan PL/SQL programot amely lekérdezi a vásárlók adatait és FOR ciklus segítségével dolgozza fel a CURSOR-t!
   declare
      v vasarlo%ROWTYPE;
      cursor cVasarlo is select * from vasarlo;
   begin
      --open cVasarlo;
      for v in cVasarlo loop
        dbms_output.put_line('mobil: '||v.mobil);
        dbms_output.put_line('cim :  '||v.cim);
      end loop;
      --close cVasarlo;
   end;
2.5.4.2.6. Írjon egy olyan PL/SQL programot amely lekérdezi a paraméterként adott aktivitású vásárlók adatait!
   declare
      mobil vasarlo.mobil%TYPE;
      cim vasarlo.cim%TYPE;
      cursor cVasarlo(a vasarlo.aktiv%type) is select mobil,cim from vasarlo where aktiv=a;
   begin
      open cVasarlo(1);
      loop
        fetch cVasarlo into mobil,cim;
        dbms_output.put_line('mobil: '||mobil||' cim: '||cim);
        exit when cVasarlo%NOTFOUND;
      end loop;
      close cVasarlo;
   end;

2.5.4.3. Módosítható kurzorok

2.5.4.3.1. Ismertesse a módosítható CURSOR definiálását!
   CURSOR cnev IS SELECT ... FOR UPDATE;
2.5.4.3.2. Ismertesse a módosítás parancsát módosítható CURSOR segítségével!
   UPDATE tabla SET mezo = ertek WHERE CURRENT OF cnev;
2.5.4.3.3. Írjon egy olyan PL/SQL programot amely az inaktív vásárlók nevét 'Lajhar Lajos'-ra módosítja!
   DECLARE
      vVasarlo vasarlo%rowtype;
      CURSOR cVasarlo IS SELECT * FROM vasarlo FOR UPDATE;
   BEGIN
      --OPEN cVasarlo;
      FOR vVasarlo IN cVasarlo LOOP
        IF vVasarlo.aktiv = 0 THEN
           UPDATE vasarlo SET nev = 'Lajhar Lajos' WHERE CURRENT OF cVasarlo;
        END IF;
     END LOOP;
   END;
2.5.4.3.4. Írjon egy olyan PL/SQL programot amely a Lajosok nevét átalakítja LajosX-re ahol X a sorszám!
   DECLARE
      i NUMBER;
      CURSOR cVasarlo IS select * from vasarlo where nev like '%Lajos%' FOR UPDATE;
   BEGIN
      i := 1;
      FOR vVasarlo IN cVasarlo LOOP
        UPDATE vasarlo SET nev = CONCAT('Lajos',i) WHERE CURRENT OF  cVasarlo;
        i := i+1;
      END LOOP;
   END;