Ugrás a fő tartalomra

PL-SQL


A PL/SQL nyelv az Oracle SQL kibővítése úgs, hogy a PL/SQL nyelvben lehetőség van az SQL adatkezelő utasításainak, a kurzor szerkezetnek és a tranzakciókezelő utasításoknak a 
használatára. Tartalmazza továbbá az alapvető vezérlési elemeket, így a WHILE ciklust 
 és az IF elágazást is. 

A Pl/SQL-ben lehetőség van saját memóriaváltozók létrehozására, melyekkel közbenső számítási eredmények tárolhatók.

A PL/SQL eljárások feldolgozása programegységekben, úgynevezett blokkokban 
történik. 


A blokk 

 BEGIN kulcsszóval kerül bevezetésre, s az END; utasítás zárja le. 

DECLARE Fő-blokk kezdete
   ... Változók, konstansok, cursor-
                                        szerkezetek és hibakezelési
elemek deklarálása

BEGIN                           Fő-blokk műveleti rész kezdete
   ... Utasítások, SQL parancsok,
Vezérlési elemek
    DECLARE                  Al-blokk kezdete
       ...     
    BEGIN                       Al-blokk műveleti része
       ...
    EXCEPTION Al-blokk hibakezelő része
       ...
    END;              Al-blokk vége

EXCEPTION Fő-blokk hibakezelő része
   ... Hibakezelő műveletek 
leírása

 END; Fő-blokk vége



A PL/SQL blokk a következő utasításokat tartalmazhatja:


:= értékadás
CLOSE kurzor lezárása (SQL utasítás)
COMMIT tranzakció sikeres lezárása (SQL utasítás)
DELETE adatok törlése az adatbázisban (SQL utasítás)
EXIT kilépés a ciklusból 
FETCH rekord beolvasás a kurzorból (SQL utasítás)
GOTO ugrás a megadott cimkére
IF feltételes elágazás
INSERT adatok beszúrása az adatbázisba (SQL utasítás)
LOCK TABLE táblák zárolása(SQL utasítás)
LOOP ciklus szervező utasítás
NULL üres utasítás
OPEN kurzor nyitása (SQL utasítás)
RAISE hibajelenség kiváltása
ROLLBACK tranzakció visszagörgetése(SQL utasítás)
SAVEPOINT tranzakció mentési pont(SQL utasítás)
SELECT..INTO lekérdezés az adatbázisból(SQL utasítás)
SET TRANSACTION tranzakció paraméterzés(SQL utasítás)
UPDATE adatok módosítása az adatbázisban(SQL utasítás)



 

Relációs műveletek

=

>

<

>=

<=

<>  (vagy !=)  - nem egyenlő

 


Fontosabb szimbólumok

( )      -   lista,

:=       -  értékadás,

||          -   konkatenáció,

--        -  megjegyzés,

/*    */   - megjegyzés.

 


Értékadás

     <Változó> := <kifejezés>;

 

Példa.

String_1 :=  ‘Hello’ || ’World’  || ’!’;

 



10.1       Vezérlési struktúrák

 

10.1.1    IF parancs

 

IF logikai_kifejezés  THEN

 parancsok;

[ELSEIF  logikai_kifejezés THEN

 parancsok; ]

 …….

[ELSE

            parancsok;]

END IF;

 

Példa.

A következő blokk IF parancsot tartalmazz.

 

DECLARE

     V_helyek_szama          Szoba.helyek_szama;

     v_Comment                VARCHAR2(35);

BEGIN

      SELECT termek INTO v_helyek_szama

                              FROM Szoba WHERE kod = 15;

      IF v_helyek_szama < 50 THEN  v_Comment := 'Kicsi';

          ELSIF v_helyek_szama < 100 THEN  v_Comment := 'Közepes';

          ELSE   v_Comment := 'Nagy';

      END IF;

END;

 



10.1.2  Üres ( NULL) parancs

 

DECLARE

 K  NUMBER := 7;

BEGIN

     IF K < 5 THEN

             INSERT INTO temp (col)       VALUES ('Nagyon kicsi');

      ELSIF Kr < 10 THEN

              INSERT INTO temp (col)       VALUES ('Megfelel');

      ELSE

        NULL; 

      END IF;

END;

 



10.1.3    Címkék és GOTO parancs

 

A parancsok előtt << címke >> állhat:

                        << címke >> parancs

A címkét a << ,>> határoló-jelek közé kell helyezni.   

GOTO << címke >>;

parancs a vezérlést a << címke >>  után álló parancsra adja. A GOTO parancs a vezérlést nem adhatja a beágyazott blokkba, vagy FOR ciklus , illetve IF parancs belsejébe.

 

Példa.

DECLARE

  k  BINARY_INTEGER := 1;

BEGIN

        LOOP

                INSERT INTO temp VALUES (k, 'Lépések száma');

                    k := k + 1;

                IF k > 50

                         THEN  GOTO  Vége;

                END IF;

         END LOOP;

   <<Vége>>    INSERT INTO test (col) VALUES ('Vége!');

END;



 

A PL/SQL-ben három fajta ciklus létezik.

 

10.1.4    Egyszerű (LOOP) ciklus 

LOOP

              <Parancsok>

            EXIT [WHEN feltététel]

       END LOOP;

 

EXIT  - feltétel nélküli kilépés a ciklusból,

EXIT WHEN <feltététel> – feltételes kilépés a ciklusból (ha a feltétel igaz).

 

Példa.

DECLARE

  K BINARY_INTEGER := 1;

BEGIN

   LOOP

         INSERT INTO test (num_col) VALUES (K);

                 K := K + 1;

                EXIT WHEN K > 50;

   END LOOP;

END;

 

Vagy

DECLARE

  k BINARY_INTEGER := 1;

BEGIN

  LOOP

      INSERT INTO test VALUES (k, 'A ciklus indexe');

           k := k + 1;   

         IF k > 50

THEN EXIT;

        END IF;

  END LOOP;

END;

 

Példa.

A következő ciklus a kurzor soraival hajtja végre a műveleteket.

 

DECLARE

  V1          VARCHAR2(20);

  V2          VARCHAR2(20);

 CURSOR Cursor_Students IS

                 SELECT nev, kod FROM students;

BEGIN

  OPEN Cursor _Students;

  LOOP

    FETCH Cursor _Students INTO V1, V2;

    EXIT WHEN Cursor_Students%NOTFOUND;

    /* Parancsok, a cilkus magja. */

  END LOOP;

  CLOSE Cursor_Students;

END;

 

A kurzornak következő fontosabb attribútumai vannak:

·        %FOUND – sort lehet leolvasni a kurzorból;

·        %NOTFOUND – nincs több sor a kurzorban;

·        %ISOPEN – meg van-e nyitva a kurzor;

 



10.1.5    WHILE ciklus 

 

WHILE   <feltétel>  LOOP

         <Parancsok>

END LOOP;

 

Példa.

DECLARE

  k BINARY_INTEGER := 1;

BEGIN

     WHILE k <= 50 LOOP

    INSERT INTO test VALUES (k, ' A ciklus indexe’);

    k := k + 1;

     END LOOP;

END;

 



10.1.6    FOR ciklus  

 

FOR <változó> IN  [REVERSE]  i_min .. i_max LOOP

            <Parancsok, Ciklus magja>

END LOOP;

 

A <változó> felveszi i_min .. i_max minden értékét növekvő, vagy REVERSE esetén csökkenő irányban, és az adott érték mellett végrehajtódik a ciklus magja.

<változó>=i_min, i_min+1, i_min+2,..., i_max;

REVERSE esetén-  <változó>I=i_max, i_max-1, i_max-2,..., i_min.

 

Példa.

BEGIN

    FOR IN 1..50 LOOP

             INSERT INTO test  VALUES (k, ' A ciklus indexe');

    END LOOP;

END;

 

BEGIN

  FOR k IN REVERSE 1..50 LOOP

        INSERT INTO test  VALUES (k, ' A ciklus indexe ');

  END LOOP;

END;




 

10.1.7  KURZOR FOR ciklus 

 

DECLARE

CURSOR Kurzor_Név IS

                 SELECT-parancs;

BEGIN

     FOR Kurzor _Változó IN kurzor

      LOOP

             Parancsok

      END LOOP;

END;

 

A kurzor FOR ciklus kényelmes eszköz a kurzor alkalmazására, mivel ebben az esetben nincs szükség a kurzor megnyitására, a sorainak leolvasására, és a kurzor bezárásába.

 

Példa.

DECLARE

...

CURSOR Cursor_Students IS

                 SELECT nev, kod FROM students;

BEGIN

            K:=0;

  FOR C_valt IN Cursor _Students;

  LOOP

            K:=K+1;

INSERT INTO test_tabla VALUES (C_valt.nevK);

  END LOOP;

END;

 




10.2       Blokkok

A PL/SQL program-konstrukcióknak blokk szerkezetűk van.

Két fajta blokk létezik

·        névtelen blokk (Anonymous block)

·        névvel rendelkező blokk (Named block).

névtelen blokk a DECLARE vagy a BEGIN kulcsszóval kezdődik és az Oracle a blokkok mindegyik végrehajtása előtt újból kell lefordítja (compile). A névtelen blokk nem tárolódhat az AB-ban, és a program-egységek nem hivatkozhatnak rá.

blokkot a következő program-egységek

  • eljárások
  • függvények
  • csomagok (modulok)
  • triggerek

tartalmazzák, és ezek a program-egységek tárolhatók az AB-ban.



 

A blokk általános struktúrája

[<<blokk_név>>]

[DECLARE ….]

BEGIN

….

[EXCEPTION….]

END;

 


névtelen blokk nem tartalmazz <<blokk_nev>>-et.

DECLARE ….- a változók deklarálása (nem kötelező része a blokknak)

BEGIN...END; - a blokk törzse, a blokk egyetlen kötelező része

EXCEPTION. – a blokk kivételkezelője (opcionális, nem kötelező része a blokknak).

 

Példa.

<<Pelda>>

DECLARE

  v_Num1              NUMBER := 3;

  v_Num2              NUMBER := 4;

  v_String1           VARCHAR2(50) := 'Hello World!';

  v_String2           VARCHAR2(50) := '-- ';

  v_OutputStr       VARCHAR2(50);

BEGIN

  INSERT INTO test (num_col, char_col)

    VALUES (v_Num1, v_String1);

  INSERT INTO test (num_col, char_col)

    VALUES (v_Num2, v_String2);

 SELECT char_col     INTO v_OutputStr

                        FROM test     WHERE num_col = v_Num1;

  DBMS_OUTPUT.PUT_LINE(v_OutputStr); 

  SELECT char_col    INTO v_OutputStr

                        FROM test     WHERE num_col = v_Num2;

  DBMS_OUTPUT.PUT_LINE(v_OutputStr);

END Pelda;



 

10.3       Változók deklarálása

A változókat a DECLARE szekcióban deklaráljuk. Az Oracle lehetőséget ad a saját típusokat szerkesztésére is. A változó deklarálása:

Változó-neve    típus  [CONSTANT] [NOT NULL]   [:= érték] ;

Leggyakoribb adattípusok:

·        VARCHAR2

·        NUMBER

·        DATE

·        BOOLEAN.

 

Numerikus típusok:

  • DEC
  • DECIMAL
  • DOUBLE PRECISION
  • INTEGER
  • INT
  • NUMERIC
  • REAL
  • SMALLINT
  • BINARY_INTEGER      (- 2147483647... 2147483647)
  • NUMBER (m, n)

 

Példák

NUMBER                12.36                          12.36

NUMBER (3)           123                             123

NUMBER (3)           1234                           HIBA

NUMBER (4,3)        1.234567                     1.235

NUMBER (4,-3)       1234                           1000

NUMBER (4,-1)       1234                           1230

 

A BOOLEAN  változó lehetséges értékei- TRUE, FALSE, NULL. Ha a lehetséges NULL értéket is figyelemben vesszük, akkor a logikai műveletek táblázatait lehet leírni,  mint három-értékű logikát.

 

AND (és) táblázat

AND

 T

F

NULL

T

T

F

Ismeretlen

F

F

F

F

NULL

Ismeretlen

F

Ismeretlen

 

OR (vagy) táblázat

OR

 T

F

NULL

T

T

T

T

F

T

F

Ismeretlen

NULL

T

Ismeretlen

Ismeretlen

 

NOT (nem) táblázat

NOT

 

T

F

F

T

NULL

Ismeretlen

 

Egy változó típusát egy AB tábla oszlopának típusa alapján is lehet deklarálni a %TYPE bejegyzéssel.

                        Name       student.nev%TYPE

 

Name változó megkapja a student tábla nev oszlopának típusát. Ez a lehetőség különösen akkor hasznos, amikor az oszlop típusa valami okból később megváltozik, de a változó típusa is a %TYPE alapján automatikusan megváltozik, ami azt jelenti, hogy a programozónak ezzel a kérdéssel nem kell foglalkozni.

 

Példa.

DECLARE

  Kod_diak    NUMBER(5) := 10000;

  V_Nev             VARCHAR2(20);                                 

BEGIN

       SELECT Nev INTO V_Nev  FROM students WHERE Id = Kod_diak;

EXCEPTION

      WHEN NO_DATA_FOUND THEN

               INSERT INTO log_table (info) VALUES ('Nem létezik a 10000 kóddal jelölt Diák!');

END;

 

Példa.

DECLARE

     v_Num1                 NUMBER := 1;

     v_Num2                 NUMBER := 2;

     v_String1   VARCHAR2(50) := 'Hello World!';

     v_String2   VARCHAR2(50) := '-- ';

     v_OutputStr            VARCHAR2(50);

 

BEGIN

   INSERT INTO test (num_col, char_col) VALUES (v_Num1,  v_String1);

   INSERT INTO test (num_col, char_col)       VALUES (v_Num2, v_String2);

           

SELECT char_col INTO v_OutputStr  FROM test WHERE num_col = v_Num1;

DBMS_OUTPUT.PUT_LINE(v_OutputStr); 

 

SELECT char_col  INTO v_OutputStr  FROM test WHERE num_col = v_Num2;

            DBMS_OUTPUT.PUT_LINE(v_OutputStr);

END;

 



10.4  Rekordok 

A PL/SQL programokban rekordokat lehet létrehozni és utána alkalmazni. A rekord deklarációval egy új adattípust hozhatunk létre. Gyakran a rekord struktúráját úgy szerkesztik, hogy az megegyezzen egy tábla struktúrájának. Ebben az esetben a tábla sorai könnyen átírhatók a rekordba.


Először a rekord-típust kell deklarálni, és utána a rekord-változó megkaphatja a rekord-típust. A rekord mezőinek típusai PL/SQL adattípusúak lehetnek, de a %TYPE használatával hivatkozhatnak egy tábla oszlopának a típusára is. A mezőkhöz NOT NULL és DEFAULT záradékok tartozhatnak. A rekord mezőjére a következő képen hivatkozhatunk

                        rekord_változó.mező

Példa.

       TYPE

 Diak_Record  IS  RECORD (

                            Diak_Kod               NUMBER (5),

                Vezetek_Nev          VARCHAR2 (20),

                Kereszt_Nev           VARCHAR2 (20));

 

             Diak_Info    Diak_Record;

 

Diak_Info változó megkapja a Diak_Record típust.   

 

DECLARE

    TYPE t_Rec1Type IS RECORD (

                      Field1      NUMBER,

                      Field2      VARCHAR2(5));

 

    TYPE t_Rec2Type IS RECORD (

                     Field1       NUMBER,

                     Field2       VARCHAR2(5));

 

  v_Rec1          t_Rec1Type;

  v_Rec2         t_Rec2Type;

/*  v_Rec1 és v_Rec2 típusai különbözőek!  */

 

BEGIN

  v_Rec1 := v_Rec2;      /*  különböző típusok,  HIBA !!!  */

  v_Rec1.Field1 := v_Rec2.Field1;

  v_Rec2.Field2 := v_Rec2.Field2;

END;

 

DECLARE

TYPE Diak_Record IS RECORD (

    Vezetek_Nev   students.vezetek_nev%TYPE,

    Kereszt_Nev    students.kereszt_nev%TYPE,

    Szak                 students.szak%TYPE);

 

     V_Diak        Diak_Record;

 

BEGIN

SELECT vezetek_nev, nev, szak INTO V_Diak

              FROM students  WHERE  ID = 10000;

END;

 



A %ROWTYPE bejegyzés alkalmazása a rekord típusok deklarálásában

DECLARE

             V_RoomRecord    rooms%ROWTYPE

 

%ROWTYPE által  a V_RoomRecord rekord megkapja a room tábla struktúráját. Ez a lehetőség akkor lehet hasznos, ha például, a room tábla struktúrája megváltoztatjuk, de a %ROWTYPE alapján a rekord struktúrája is automatikusan megváltozik.

Az SQL parancsok változókat tartalmazhatnak, és ezzel összekapcsolhatók egymással egy program parancsai.

 

Példa.

DECLARE

  v_NumCredits  classes.num_credits%TYPE;

BEGIN

   v_NumCredits := 3;

  UPDATE Classes SET num_credits = v_NumCredits    

             WHERE szak = 'MAT'  AND tantargy = 101;

END;

 

Példa.

DECLARE

  v_DiakRecord  students%ROWTYPE;

  v_szak              classes.szak%TYPE;

  v_ tantargy                      classes.tantargy%TYPE;

 

BEGIN

SELECT *  INTO V_DiakRecord

    FROM students     WHERE id = 10000;

 

SELECT department, course  INTO v_szak, v_ tantargy

    FROM classes WHERE kod = 99997;

END;

 

10.5   Objektum típusok

Az Objektumrelációs adatbázis-kezelő rendszer (ORDBMS – Object-Relation DataBase Management System) – támogatja mind a relációs eszközöket (kulcs, ...) mind az objektumorientált eszközöket (módszerek, ... ).

Az alkalmazások szempontjából fontos, hogy a PL/SQL programokban bizonyos összetett adat-struktúrákat egységesen lehessen kezelni. Ezzel a tulajdonsággal rendelkezik az objektum típus, amelyet absztrakt adattípusnak lehet tekinteni.

Az absztrakt adattípus – olyan adattípus, amely több altípusból tevődik össze. Az objektum típus attribútumokat és metódusokat tartalmazhat. Általános esetben, amikor az objektum típus metódusokat is tartalmaz, az két részből áll:

  • az objektum deklarálásából (specifikation);
  • az objektum törzséből.

Az objektum deklarálása az attribútumokat és a hozzá tartozó metódusok listáját tartalmazza. Az objektumban legalább egy attribútumnak kell lennie. Az objektumban a metódusok hiányozhatnak. Az objektum törzse a metódusok kódját tartalmazza. Egy objektumot csak az a felhasználó hozhat létre, aki a CREATE TYPE privilégiummal rendelkezik. A CREATE TYPE a RESOURCE szerephez tartozik. Más felhasználó akkor hozhat létre új típust, ha CREATE ANY TYPE privilégiummal rendelkezik. Ezek a feltételek a CREATE TYPE BODY parancsra is érvényesek.

 



10.5.1 Objektum típus létrehozása

 

CREATE [OR REPLACE] TYPE [felhasználó].típus_neve

AS OBJECT

 (attribútum lista, [,metódusok listája])

 

Az attribútum deklarálása hasonlít a változók deklarálása a blokkban, de nem tartalmazhat %TYPE opciót, nem kaphat kezdő értéket, és a NOT NULL megszorítás sem alkalmazható.

Az objektum az AB szótárához tartozik, és mivel az objektumnak tulajdonosa kell, hogy legyen, ezért, ha a CREATE parancsban nincs megadva a felhasználó neve, akkor a deklarálandó objektumnak a tulajdonosa az adott felhasználó lesz. Egy másik felhasználó esetén annak a nevét meg kell adni. Csak az a felhasználó alkalmazhatja az objektumot, aki EXECUTE privilégiummal rendelkezik. 

Hivatkozás az objektum attribútumára:

                                   Objektum_neve.attribútum

 

Példa.

CREATE OR REPLACE TYPE StudentObj  AS OBJECT (

            ID                                            NUMBER(5),

            vezetek_nev                             VARCHAR2(20),

            kereszt_nev                              VARCHAR2(20),

            szak                                         VARCHAR2(30),

            kreditek                                   NUMBER(3) );

 

 

Példa.

CREATE OR REPLACE TYPE Car  AS OBJECT (

            Model                                      VARCHAR2(20),

            Color                                        VARCHAR2(20),

            Cost                                         NUMBER(6) );

 

CREATE OR REPLACE TYPE Car_Garage  AS  VARRAY(50) OF Car;

 

CREATE OR REPLACE TYPE Garage  AS OBJECT (

            Adress                                     VARCHAR2(100),

            CarCount                                 NUMBER

AllCar                                       Car_Garage);

 

Car – objekt típus az autó egyedeket, a Garage – a garázs egyedeket, a Car_ Garage –típus pedig az autók csoportjait tartalmazzák.

 



10.5.1.1 Objektum típusú változó deklarálása

DECLARE    Változó    Objektum_típus;

 

DECLRE

MyCar                        Car;

MyGarage                   Garage;

 

A létrehozott típusok nem tartalmaznak metódusokat, ezért ebben az esetben nincs szükség az objektum törzsének deklarálására.

 



10.5.2    Metódusok

Mint már említettük, az objektum deklarálása tartalmazhat az objektumhoz tartozó metódusok listáját. A metódusok listája a következő deklarálási elemeket tartalmazhat:

[STATIC| MEMBER] PROCEDURE eljárás_deklarálása,

[STATIC| MEMBER] FUNCTION függvény_deklarálása,

……………………

 

Példa.

Car objektumot kiegészítjük metódusokkal:

CREATE OR REPLACE TYPE Car  AS OBJECT (

            Model                                      VARCHAR2(20),

            Color                                        VARCHAR2(20),

            Cost                                         NUMBER(6),

MEMBER FUNCTION GetCarInfo RETURN VARCHAR2,

PRAGMA RESTRICT_REFERENCES(GetCarInfo) );

 

A metódusokat az attribútumok után kell leírni. A PRAGMA RESTRICT_REFERENCES záradék engedélyezi a metódusokra való hivatkozást az SQL-parancsokból.

 



10.5.2.1  Metódusok implementálása

A metódusok kódját az objektum törzsében kell leírni:

CREATE [OR REPLACE] TYPE BODY [felhasználó].típus_neve AS| IS

<metódusok_törzseinek_listája>

 

Példa.

CREATE OR REPLACE TYPE BODY Car  AS

MEMBER FUNCTION GetCarInfo RETURN VARCHAR2

IS

BEGIN

RETURN Modell || ’’ || Color || ‘’ || Cost;

END GetCarInfo;

END;

 

Hivatkozás a metódusra:

                       Objektum_neve.Metódus

 

Példa.

Az SQL*Plus-ban végrehajtjuk a következő programot:

DECLARE

            Car1  Car:=

            Car(’Audi’, ’Piros’, 3000000);

            Car2  Car:=

            Car(’BMW’, ’Fehér’, 2500000);

BEGIN

DBMS_OUTPUT.PUT_LINE(Car1.GetCarInfo);

DBMS_OUTPUT.PUT_LINE(Car2.GetCarInfo);

END;

 

Audi    Piros    3000000

BMW  Fehér   2500000

PL/SQL  procedure successfully completed.




 

10.5.3    Kezdő érték bevitele az objektumba

Az objektum kezdő értékekeit a konstruktor által legegyszerűbben megadni. Az Oracle mindegyik objektum-típushoz létrehoz automatikusan egy  konsztruktor-függvényt.

Például, a Garage objektum konstruktora a következő függvény lesz:

FUNCTION Garage(

            Adress                         IN VARCHAR2(100);

                       CarCount                     IN  NUMBER

AllCar                         IN  CarGarage)

           RETURN Garage;

 



10.5.4    Objektumok módosítása és törlése

ALTER TYPE [felhasználó.]<típus_neve>

            REPLACE AS OBJECT

                       (<OBJECT-típus deklaráció>);

A parancsban nem csak a módosított elemeket kell megadni, hanem újból kell deklarálni azokat az elemeket, amelyek nem váltóznak. A metódus kódjának a módosítása a

CREATE OR REPLACE TYPE BODY [felhasználó.]típus_neve AS| IS

<metódusok_törzseinek_listája>

paranccsal történik.

 



Objektum-típus törlése

Az objektum-típus törlése több változatban történhet: 

·        DROP TYPE [felhasználó.]típus_neve

Ebben az esetben az Oracle csak akkor törli az objektum-típust, ha más objektum-típus nem hivatkozik rá.

·        DROP TYPE [felhasználó.]típus_neve FORCE

FORCE záradék az objektum-típus törlését engedélyezi még akkor is, ha az adott objektum-típusra más AB-objektum-típus hivatkozik.

·        DROP TYPE BODY [felhasználó.]típus_neve

Ez a parancs törli az objektum-típus törzsét, de nem törli az objektum-típus deklarációját.

 



10.5.5    Objektumok az adatbázisban 

Az Oracle fontos tulajdonsága, hogy az objektumokat az AB táblákban lehet tárolni. Ez két változatban valósítható meg. Az objektumot tárolni lehet, mint

·        Objektum-oszlop;

·        Objektum-sor.

 



10.5.5.1 Objektum-oszlop

Ebben az esetben az objektum a táblában ugyanúgy oszloponként tárolódik, mint a többi elsődleges típus.

 

Példa.

CREATE TABLE Cars(

            Key               NUMBER PRIMARY KEY,

OneCar          Car);

 

Cars tábla második oszlopa objektum-típusú.

            INSERT INTO Cars VALUES(1,

                                   Car(’Skoda’, ’Piros’, 2000000 ) );

            INSERT INTO Cars VALUES(2,

                                   Car(’Lada’, ’Zöld’, 1200000 ) );

 

Az adatok bevítelére a táblába az INSERT parancs a Car konstruktort alkalmazza.

Car tábla tartalmát az SQL*Plus-ban így lehet megjeleníteni

 

SELECT * FROM Cars;

 

KEY                        ONECAR(MODEL, COLOR, COST)

  1                               CAR(’Skoda’, ’Piros’, 2000000)

  2                               CAR(’Lada’, ’Zöld’, 1200000 )

 

10.5.5.2 Objektum-sor

Ebben az esetben az objektum a tábla egész sorával azonosul, és a tábla nem tartalmazhat más oszlopokat.

CREATE TABLE Tábla_név  OF objektum-típus;

 

Példa.

CREATE TABLE CarRows OF Car;

 

INSERT INTO CarRows VALUES(Car(’Skoda’, ’Piros’, 2000000 ) );

            INSERT INTO CarRows VALUES(Car(’Lada’, ’Zöld’, 1200000 ) );

 

SELECT * FROM CarsRows;

 

MODEL     COLOR    COST

             Skoda        Piros        2000000

             Lada          Zöld        1200000

 

10.5.6    Objektumok az SQL parancsokban

Az SQL-parancsok végrehajtásának módja nem változik, ha egy tábla objektum-oszlopokat is tartalmaz. Például, egy objektum értékét egy vele azonos típusú objektum típusú változóba lehet átmásolni. Végrehajtunk néhány DML-parancsot a Cars táblával.

 

DECLARE

            C         CAR;

           Id         NUMBER;

BEGIN

     SELECT MAX(Key)  INTO Id FROM Cars;

     SELECT OneCar  INTO FROM Cars

                                            WHERE Key=Id;

C.Model:=’BMW’;

C.Color:=’Fekete’;

INSERT INTO Cars VALUES (Id+1, C);

END;

 

Az eredmény:

SELECT * FROM Cars;

 

KEY    ONECAR(MODEL, COLOR, COST)

------    ---------------------------------------------

             1         CAR(’Skoda’, ’Piros’, 2000000)

             2         CAR(’Lada’, ’Zöld’,   1200000 )

 3         CAR(’BMW’,’Fekete’, 1200000)

 



Az SQL parancsokban az objektum attribútumaira csak úgy hivatkozhatunk, hogy megadjuk a tábla másodlagos (alias) nevét is.

 

Példa.

SELECT C.OneCar.Model FROM Cars C;

 

ONECAR.MODEL

------------------------

Skoda

            Lada

BMW

 

Akkor is szükség van a tábla másodlagos nevére, ha hivatkozni akarunk az objektum metódusára.

SELECT C.OneCar.GetCarInfo() FROM Cars C;

 

C.ONECAR.GETCARINFO()

----------------------------

Skoda  Piros      2000000

            Lada    Zöld      1200000

BMW  Fekete   1200000

 

Az objektum-sorok esetén az objektum attribútumait ugyanúgy lehet alkalmazni, mintha azok hagyományos relációs tábla oszlopai lennének.

 

SELECT C.OneCar.GetCarInfo() FROM CarsRows C;

 

C.GETCARINFO()

----------------------------

Skoda  Piros      2000000

            Lada    Zöld      1200000

BMW  Fekete   1200000



 

10.6     Összetett konstrukciók (COLLECTIONS)

Az Oracle a következő összetett konstrukciót tartalmaz:

  • Indexelt táblák (Index-by tables)
  • Beágyazott táblák (Nested tables)
  • Tömbök (Változó hosszuságuak),

amelyek objektum tulajdonsággal rendelkeznek, mivel tartalmaznak attribútumokat és metódusokat.

Az indexelt táblák és a beágyazott táblák a PL/SQL táblákat alkotják. beágyazott táblákat az AB táblákban is lehet tárolni (ezért kapták a nevüket). Az indexelt táblák nem tárolódhatnak az AB táblákban, és csak a PL/SQL programokban alkalmazhatók.

 



10.6.1  Indexelt táblák 

Az indexelt táblát nem azonosak az adatbázis táblával!.

Az indexelt tábla szintaxisa hasonlít a tömb szintaxisára. Mielőtt egy indexelt táblát deklarálnánk, egy PL/SQL blokkban létre kell hozni a típusát:

 

TYPE tábla_tipus IS TABLE OF tipus

                                INDEX BY BINARY_INTEGER;

 

A tábla típusa objektum típusú is lehet.

Az INDEX BY BINARY_INTEGER paraméter kulcs jellegű, kötelező az indexelt táblák esetén, de a beágyazott táblákban nem alkalmazhatók.

Az indexelt tábla két oszlopot tartalmaz:

  • KEY (kulcs)
  • VALUE (érték)

 

A kulcs típusa – BINARY_INTEGER, a kulcs lehetséges értékei

                        (-2147483647...+ 2147483647),

a VALUE típusát a deklarációban kell megadni.

Nem kötelező, hogy a tábla elemeinek indexei egymás utáni értékeket kapjanak.   

 

Példa.

TYPE  t_CharacterTable  IS TABLE OF VARCHAR2(10)

                                INDEX BY BINARY_INTEGER;

 

Az indexelt tábla deklarálása:

V_Characters     t_CharacterTable;

 

Példa.

DECLARE

TYPE  t_NameTable  IS TABLE OF  students.vezetek_nev%TYPE

                                INDEX BY BINARY_INTEGER;

TYPE  t_DateTable  IS TABLE  OF DATE

                                INDEX BY BINARY_INTEGER;

 

V_ Names     t_NameTable;

V_ Dates       t_DateTable;

 

A tábla elemeire az index által hivatkozhatunk

                                   Tabla_név(index)

 

BEGIN

     V_ Names(1):= ’Szabó’;

     V_ Dates(-4):=   SYSDATE - 1;

END;

 

SET SERVEROUTPUT ON

DECLARE

  TYPE      t_StudentTable IS TABLE OF students%ROWTYPE

                                                     INDEX BY BINARY_INTEGER;

V_Diak            t_StudentTable;

 

BEGIN

  SELECT * INTO V_Diak(10001)

            FROM students WHERE id = 10001;         

  V_Diak(10001).vezetek_nev := 'Kovács';

  DBMS_OUTPUT.PUT_LINE(V_Diak(10001).vezetek_nev);

END;

 



10.6.2     Beágyazott táblák

A Beágyazott táblára úgy tekinthetünk, mint egy adatbázis táblára, amelynek két oszlopa van

  • KEY (kulcs)
  • VALUE (érték)

(mint az indexelt táblában).

A beágyazott tábla egy AB tábla oszlopa lehet.

beágyazott tábla típusának deklarálása:

TYPE tábla_típus IS TABLE OF típus;

 

A tábla elemeinek inicializálása a konstruktor-függvény használatával történik. A létrehozott tábla-elemek kezdő indexe csak egy lehet, és a következő értékei mindég csak eggyel növekedhetnek.

 

Példa.

DECLARE

            K         INTEGER;

TYPE  Num_Tab  IS TABLE OF  NUMBER;

Tab_1    Num_Tab :=Num_Tab(-1);

Tab_2    Num_Tab :=Num_Tab(1, 2, 3, 5, 7);

Tab_3    Num_Tab :=Num_Tab( );

BEGIN

Tab_1(1):=12345;

FOR IN 1..5 LOOP

DBMS_OUTPUT.PUT(Tab_2(K) || ‘ ‘);

END LOOP;

DBMS_OUTPUT.NEW_LINE;
END;

 

1 2 3 5 7

 

A példában az inicializáláskor a táblák elemei a következő értékeket kapták:

Tab_1(1)=( -1),

Tab_2(1)=(1), Tab_2(2)=(2), Tab_2(3)=(3), Tab_2(4)=(5), Tab_2(15=(7);

A Tab_3 létezik, de egyetlen elemet sem tartalmaz. A programban a Tab_1 tábla első eleme megváltozik (12345 értéket kap). 

 


10.6.3    Tömbök

Az Oracle-ban használható tömb megfelel a C és a Java nyelvekben alkalmazott tömböknek. A tömb elemeire ugyanúgy lehet hivatkozni, mint az indexelt, vagy a beágyazott táblák elemeire. A tömb indexnek a kezdő értéke mindig egye, és eggyel növekszik.

      A tömb típus deklarálása:

      TYPE típus_név IS VARRAY <maximális_méret>

                                         OF elemek_típusa [NOT NULL];

 

Az elemek_típusa alap-, rekord, vagy objektum típusú lehet. Ezenkívül, a %TYPE segítségével az AB tábla oszlop típusát lehet alkalmazni, a %ROWTYPE pedig az AB tábla sorai alapján egy rekord típust hoz létre.

NOT NULL nem engedélyezi, hogy a tömb üres elemeket tartalmazzon.

 

Példa.

      TYPE Num_List IS VARRAY (20)

                             OF NUMBER(3) NOT NULL;

      TYPE Car_List IS VARRAY (100)

                             OF CarArr%ROWTYPE;

      TYPE Car_Arr IS VARRAY (20)

                             OF Car;

 

A tömb kezdő értékeit a konstruktorok által lehet megadni.

 

DECLARE

      TYPE Var_Num IS VARRAY (20)  OF NUMBER;

      Var_1   Var_Num := Var_Num(1, 2, 3);

BEGIN

DBMS_OUTPUT.PUT_LINE(Var_1(1));

Var_1(1):=15;

DBMS_OUTPUT.PUT_LINE(Var_1(1));

       END;

 

            1

15

A tömb méretét az EXTEND metódussal lehet növelni.

 



10.6.4     Összetett konstrukciók metódusai

Mivel a tömbök és beágyazott táblák objektum típusú konstrukciók, azok metódusokkal is rendelkeznek, az indexelt táblákhoz pedig attribútumok tartoznak. A metódusokra, mint az attribútumokra is s következő képen lehet hivatkozni:

            konstrukció_eleme.metódus

vagy

            konstrukció_eleme.attribútum

A metódusok csak a blokkokban alkalmazhatók, és nem az SQL-parancsokban.

Az Oracle felismeri a következő beépített metódusokat:

  • EXISTS          (az eredmény típusa – BOOLEAN)
  • COUNT         (az eredmény típusa – NUMBER)
  • FIRST            (az eredmény típusa – BINARY_INTEGER)
  • LAST             (az eredmény típusa – BINARY_INTEGER)
  • NEXT             (az eredmény típusa – BINARY_INTEGER)
  • PRIOR           (az eredmény típusa – BINARY_INTEGER)
  • EXTEND       (új elemeket szúr be a konstrukcióba)
  • TRIM             (törli a konstrukció utolsó elemeit)
  • DELETE        (törli az elemeket a konstrukcióban)

 

 



10.6.4.1  EXISTS metódus.

Az EXISTS metódust akkor alkalmazzuk, ha akarjuk megállapítani, hogy létezik-e az n-ik elem

EXISTS(n)

A metódus eredménye TRUE, ha az adott elem létezik, különben FALSE.

 

Példa.

DECLARE

  TYPE t_Vezetek_NevTable IS TABLE OF students.vezetek_nev%TYPE

    INDEX BY BINARY_INTEGER;

  Vezetek_Nevs  t_Vezetek_NevTable;

BEGIN

  Vezetek_Nevs(1) := 'Szabó';

  Vezetek_Nevs(3) := 'Kiss';

 

IF Vezetek_Nevs.EXISTS(1) THEN

    INSERT INTO test (char_col) VALUES

      ( 'Az 1 sor létezik!');

  ELSE

    INSERT INTO test (char_col) VALUES

      (' Az 1 sor nem létezik!!');

  END IF;

  IF Vezetek_Nevs.EXISTS(2) THEN

    INSERT INTO test (char_col) VALUES

      (' A 2 sor létezik!');

  ELSE

    INSERT INTO test (char_col) VALUES

      (' A 2  sor nem létezik!');

  END IF;

END;



 

10.6.4.2 COUNT metódus

A COUNT metódus nem tartalmaz paramétereket, és az eredménye a konstrukció elemeinek száma.

 

Példa.

DECLARE

    TYPE Tabla_1 IS TABLE OF NUMBER

                               INDEX BY BINARY_INTEGER;

 

  Szamok                     Tabla_1;

  Osszesen                   NUMBER;

BEGIN

      FOR k IN 1..50 LOOP

                 Szamok(k) := k;

      END LOOP;

       Osszesen := Szamok.COUNT;

     DBMS_OUTPUT.PUT_LINE(Osszesen);

END;

            50



 

10.6.4.3 NEXT, PRIOR, FIRST és LAST metódusok

NEXT metódus növeli a kulcs (KEY) értékét. A

                                   NEXT(n)

visszaadja az n után következő indexet (növekvő irányban),

a PRIOR metódus pedig csökkenti a kulcs (KEY) értékét

                                   PRIOR(n)

az n előtti indexet kapjuk (csökkenő irányban).

Ha az adott értékű kulcs (n) nem létezik, akkor a NEXT és PRIOR eredménye NULL lesz.

FIRST metódus az index első értékét adja, a LAST pedig – az utolsó értékét. A FIRST és a LAST metódusok nem tartalmaznak paramétert.

 

Példa.

DECLARE

  TYPE Nev_Table IS TABLE OF students.nev%TYPE

    INDEX BY BINARY_INTEGER;

  v_Nev             Nev_Table;

  v_Index  BINARY_INTEGER;

BEGIN

  -- Új sorokat szúrunk be a táblába.

  v_Nev(43) := 'Sándor';

  v_Nev(50) := 'Mária';

  v_Nev(47) := 'Iván';

 

   v_Index := v_Nev.FIRST;   -- v_Index=43

   v_Index := v_Nev.LAST;      -- v_Index=50

END;

 

Példa.

DECLARE

  TYPE Szakok IS TABLE OF students.szak%TYPE

    INDEX BY BINARY_INTEGER;

  v_Szak          t_Szakok;

  v_Index          BINARY_INTEGER;

BEGIN

  v_Szak(-7) := 'Számítástechnika';

  v_Szak(4) := 'Történelem';

  v_Szak(5) := 'Matematika';

 

  v_Index := v_Szak.FIRST;

  LOOP                       -- a v_Index a következő értékeket kapja a ciklusban- -7, 4, 5.

         INSERT INTO test (num_col, char_col)  VALUES (v_Index, v_Szak(v_Index));

    EXIT WHEN v_Index = v_Szak.LAST;

         v_Index := v_Szak.NEXT(v_Index);

  END LOOP;

END;

 

Példa.

DECLARE

  TYPE Char_Tab IS TABLE OF CHAR(1);

 Char_1                 Char_Tab:= Char_Tab(‘a’, ’b’, ’c’, ’d’, ’e’);

  Ind                      INTEGER;

BEGIN

            Ind:=Char_1.FIRST;

 

WHILE   Ind<= Char_1.LAST          LOOP

    DBMS_OUTPUT.PUT(Char_1(Ind));

            Ind:=Char_1.NEXT(Ind);

END LOOP;

 

    DBMS_OUTPUT.NEW_LINE;

            Ind:=Char_1.LAST;

WHILE   Ind >= Char_1.FIRST                   LOOP

    DBMS_OUTPUT.PUT(Char_1(Ind));

            Ind:=Char_1.PRIOR(Ind);

END LOOP;

    DBMS_OUTPUT.NEW_LINE;

 

END;

 

abcde

edcba

 



10.6.4.4 EXTEND metódus

Az EXTEND metódus új elemeket szúr be a konstrukcióba. A metódus három formában alkalmazható

·        EXTEND

·        EXTEND(n)

·        EXTEND(n, i)

 

Az EXTEND paraméterek nélkül a konstrukció végére NULL (üres) elemet szúr be;

EXTEND (n) a konstrukció végére  NULL (üres) elemet szúr be;

EXTEND (n, i) az i számú elemet n-szer a konstrukció végére másolja át.

Ha a konstrukció a NOT NULL záradékkal volt létrehozva, akkor az EXTEND csak az utolsó formájában alkalmazható.

 

Példa.

A SQL*Plus-ban:

 

DECLARE

  TYPE Num_Tab IS TABLE OF NUMBER;

  TYPE Num_Var IS VARRAY(25) OF NUMBER;

  Tab_1  Num_Tab :=Num_Tab(1, 2, 3, 4, 5);

  Tab_2  Num_Var :=Num_Var(1, 2, 3, 4, 5);

 

BEGIN

  Tab_1(26) := -7;   -- A Tábla 26-ik eleme nem létezik

    EXCEPTION

       WHEN SUBSCRIPT_BEYOND_COUNT THEN

       DBMS_OUTPUT.PUT_LINE(‘A Tábla 26-ik eleme nem létezik’);

   END;

 

--A PL/SQL táblát lehet bővíteni:

            Tab_1.EXTEND(30);

 Tab_1(26) := -7;        -- most már Tab_1(26) létezik

 

-- A tömböt csak a maximális méretig (25) lehet bővíteni.

  Tab_2(26) := -7;

    EXCEPTION

       WHEN SUBSCRIPT_OUTSIZE_LIMIT THEN

       DBMS_OUTPUT.PUT_LINE(‘Nem sikerült a tömb méretét növelni a 30-ik elemig’);

   END;

END;

 



10.6.4.5 TRIM metódus

TRIM metódus törli a konstrukció utolsó elemét (elemeit). Két formája létezik

                        TRIM     és

                        TRIM(n)

TRIM az utolsó elemet törli. A TRIM(n) törli az utolsó n elemet. Ha n>COUNT, akkor SUBSCRIPT_BEJOND_COUNT kivételes szituáció következik be. A TRIM végrehajtása után a COUNT értéke is megváltozik.

 



10.6.4.6  DELETE metódus

DELETE metódus egy vagy több elemet töröl az indexelt vagy beágyazott táblából. DELETE a tömbök esetén nem alkalmazható. Három formája van

DELETE;

DELETE(n);

DELETE(n, m)

 

DELETE törli az egész táblát.

DELETE(n) azt az elemet törli, amelynek az indexe = n.

DELETE(n, m) azokat az elemeket törli, amelyeknek az indexe n és m között van.

 

 

Példa.

DELETE (5)                          -- törli az 5. elemet

DELETE(5, 8)                      --  törli az 5,6,7,8 indexű elemeket

 

DECLARE

  TYPE Tabla_ertekek IS TABLE OF VARCHAR2(10)

                                                     INDEX BY BINARY_INTEGER;

  Ertekek                     Tabla_ertekek;

BEGIN

  Ertekek(1) := 'Egy';

  Ertekek(3) := 'Három';

  Ertekek(-2) := 'Minusz kettő';

  Ertekek(0) := 'Zeró';

  Ertekek(100) := 'Száz';

 

  DBMS_OUTPUT.PUT_LINE('Törlés előtt, összesen=' || Ertekek.COUNT);

  Ertekek.DELETE(100); 

  DBMS_OUTPUT.PUT_LINE('Első törlés után, összesen=' || Ertekek.COUNT);

  Ertekek.DELETE(1,3);  -- Törli az 1 és 3 indexű elemeket

  DBMS_OUTPUT.PUT_LINE('Második törlés után, összesen=' || Ertekek.COUNT);

  Ertekek.DELETE;       -- Törli az összes elemet

  DBMS_OUTPUT.PUT_LINE(' Utólsó törlés után, összesen=' || Ertekek.COUNT);

END;

 



10.6.5   Összetett konstrukciók alkalmazása az adatbázisban

            A beágyazott táblákat és a tömböket (indexelt táblákat nem) lehet tárolni az adatbázisban. Az összetett konstrukciókat akkor lehet bevinni az AB táblába, ha mint az SQL, mint a PL/SQL-parancsokból láthatók (elérhető) a konstrukció típusa. Ez csak akkor lehetséges, ha a konstrukció a CREATE TYPE paranccsal volt létrehozva, mint objektum típus, és nem lokálisan egy PL/SQL-blokkban.

 

Példa.

CREATE OR REPLACE TYPE NameList AS

                        VARRAY(20)  OF VACHAR2(30);

 

Miután létrehoztuk a NameList típust, utána ezt a típust alkalmazhatjuk a blokkokban, eljárásokban, és csomagokban a változók deklarálására.

 

DECLARE

             TYPE DateList AS

                        VARRAY(10)  OF DATE;

            v_DateList           DateList;

            v_Names              NameList;

BEGIN

            NULL;

END;

 

Az a típus, amelyet a CREATE OR REPLACE TYPE parancs hozott létre (például, NameList), az globális típus. A DateList- lokális típus, mivel az csak az adott blokkban érvényes, és az AB-ból nem érhető el.

            Az AB tábla oszlopa tömb-típusú is lehet. Ebben az esetben a tábla egy sorához egy tömb tartozik. Tehát, a különböző sorok más és más tömböket tartalmazhatnak.

 

Példa.

CREATE OR REPLACE TYPE ArrStr AS

                        VARRAY(20)  OF VACHAR2(30);

 

CREATE TABLE Varray_Tab (

                        Id            NUMBER PRIMARY KEY,

                        Name     VARCHAR2(20),

                        VarStr   ArrStr);

 

INSERT INTO Varray_Tab VALUES(1, ’Gyümölcsök’, ArrStr(’Körte’, ’Alma’, ’Szilva’));

INSERT INTO Varray_Tab VALUES(2, ’Zöldségek’, ArrStr(’Káposzta’, ’Paradicsom’));

 

Az AB tábla oszlopában beágyazott táblák is tárolódhatnak. Ebben az esetben a tábla mindegyik sora tartalmaz egy hozzá tartozó beágyazott táblát.

 

Példa.

CREATE OR REPLACE TYPE Nested_Table AS

                                   TABLE  OF NUMBER;

 

CREATE TABLE Test_Nested (

                        Id                        NUMBER,

                        Name                  VARCHAR2(20),

                        Tab_Values        Nested_Table)

NESTED TABLE Tab_Values STORE AS N_Tab;

 

Az N_Tab a tárolási tábla (store table) neve, és ez a tábla a Tab_Values beágyazott táblákat tárolja. Ez azt is jelenti, hogy a Test_Nested tábla a beágyazott táblákat direkt módon nem tárolja, hanem csak a mutatókat tárolja a beágyazott táblákra. Új sorok beszúrása a tárolt táblák esetén is az INSERT SQL DML paranccsal történhet.

 

INSERT INTO Test_Nested VALUES(1, ’első sor’, Nested_Table(1, 1, 1, 2, 2, 3, 3));

INSERT INTO Test_Nested VALUES(2, ’második sor’, Nested_Table(5, 6));

INSERT INTO Test_Nested

VALUES(1, ’harmadik sor’, Nested_Table(7, 8, 9, 10, 11,  12));

 

Az adatok módosítására az UPDATE parancsot alkalmazzuk, az adatok törlésére pedig – a DELETE parancsot. Az összetett konstrukciókat az AB táblából a SELECT paranccsal változókba lehet átírni (mint alap típusú adatokat). Amikor egy beágyazott táblát átírunk egy PL/SQL változóba, akkor a változó elemei megkapják az index értékeit növekvő sorrendbe egytől kezdve, az index maximális értéke pedig COUNT lesz. A következő példák bemutatják, hogy kaphatjuk meg a beágyazott tábla elemeit.

 

SELECT Tab_Values FROM Test_Nested

                                                            WHERE Id  = 1;

 

TAB_VALUES

-------------------

NESTEDTABLE(1, 1, 1, 2, 2, 3, 3)

 

Egy másik lehetőség-

 

SELECT * FROM TABLE (SELECT Tab_Values

FROM Test_Nested              WHERE Id  = 1);

 

            COLUMN_VALUE

            ------------------------

                        1

1

1

2

2

3                    

3         

 

SELECT * FROM TABLE (SELECT Tab_Values

FROM Test_Nested              WHERE Id  = 1)

WHERE Column_Value>1

ORDER BY Column_Value DESC;

 

            COLUMN_VALUE

            ------------------------

                        3                     

3         

2

2

 

SELECT * FROM TABLE (SELECT Varray_Tab.VarStr

FROM Varray_Tab  WHERE Id  = 1);

 

            COLUMN_VALUE

            ------------------------

            Körte

           Alma

           Szilva

Megjegyzések