A skalártípusok mindegyike beépített típus, a STANDARD csomag tartalmazza őket. Ezek tartományának elemei atomiak. Ezzel szemben az összetett típusok tartományának elemei mindig egy-egy adatcsoportot reprezentálnak. Ezeket a típusokat mindig felhasználói típusként kell létrehozni. Két összetett típuscsoport van. Az egyikbe tartozik a rekord, amely heterogén, összetett típus, a másikba tartozik az asszociatív tömb, a beágyazott tábla és a dinamikus tömb. Ez utóbbiakat összefoglaló néven kollekciótípusoknak hívjuk. A kollekciótípusokkal a 12. fejezet foglalkozik.
A rekord logikailag egybetartozó adatok heterogén csoportja, ahol minden adatot egy-egy mező tárol. A mezőnek saját neve és típusa van. A rekordtípus teszi lehetővé számunkra, hogy különböző adatok együttesét egyetlen logikai egységként kezeljünk. A rekord adattípus segítségével olyan programeszközöket tudunk deklarálni, amelyek egy adatbázistábla sorait közvetlenül tudják kezelni. Egy rekordtípus deklarációja a következőképpen történik:
TYPE név IS RECORD(
mezőnév típus [[NOT NULL] {:=|DEFAULT}kifejezés]
[,mezőnév típus [[NOT NULL] {:=|DEFAULT} kifejezés]]…);
A név a létrehozott rekordtípus neve, a továbbiakban deklarációkban a rekord típusának megadására szolgál.
A mezőnév a rekord mezőinek, elemeinek neve.
A típus a REF CURSOR kivételével bármely PL/SQL típus lehet.
A NOT NULL megadása esetén az adott mező nem veheti fel a NULL értéket. Ha futási időben mégis ilyen értékadás következne be, akkor kiváltódik a VALUE_ERROR kivétel. NOT NULL megadása esetén kötelező az inicializálás.
A :=|DEFAULT utasításrész a mező inicializálására szolgál. A kifejezés a mező kezdőértékét határozza meg.
Egy rekord deklarációjának alakja:
rekordnév rekordtípus_név;
1. példa
DECLARE
/* Rekorddefiníciók */
-- NOT NULL megszorítás és értékadás
TYPE t_aru_tetel IS RECORD (
kod NUMBER NOT NULL := 0,
nev VARCHAR2(20),
afa_kulcs NUMBER := 0.25
);
-- Az előzővel azonos szerkezetű rekord
TYPE t_aru_bejegyzes IS RECORD (
kod NUMBER NOT NULL := 0,
nev VARCHAR2(20),
afa_kulcs NUMBER := 0.25
);
-- %ROWTYPE és rekordban rekord
TYPE t_kolcsonzes_rec IS RECORD (
bejegyzes plsql.kolcsonzes%ROWTYPE,
kolcsonzo plsql.ugyfel%ROWTYPE,
konyv plsql.konyv%ROWTYPE
);
-- %ROWTYPE
SUBTYPE t_ugyfel_rec IS plsql.ugyfel%ROWTYPE;
v_Tetel1 t_aru_tetel; -- Itt nem lehet inicializálás és NOT NULL!
v_Tetel2 t_aru_tetel;
.
.
.
Egy rekord mezőire minősítéssel a következő formában tudunk hivatkozni:
rekordnév.mezőnév
2. példa
v_Tetel1.kod := 1;
Rekordot nem lehet összehasonlítani egyenlőségre vagy egyenlőtlenségre és nem tesztelhető a NULL értéke sem.
Komplex példa
DECLARE
/* Rekorddefiníciók */
-- NOT NULL megszorítás és értékadás
TYPE t_aru_tetel IS RECORD (
kod NUMBER NOT NULL := 0,
nev VARCHAR2(20),
afa_kulcs NUMBER := 0.25
);
-- Az előzővel azonos szerkezetű rekord
TYPE t_aru_bejegyzes IS RECORD (
kod NUMBER NOT NULL := 0,
nev VARCHAR2(20),
afa_kulcs NUMBER := 0.25
);
-- %ROWTYPE és rekordban rekord
TYPE t_kolcsonzes_rec IS RECORD (
bejegyzes plsql.kolcsonzes%ROWTYPE,
kolcsonzo plsql.ugyfel%ROWTYPE,
konyv plsql.konyv%ROWTYPE
);
-- %ROWTYPE
SUBTYPE t_ugyfel_rec IS plsql.ugyfel%ROWTYPE;
v_Tetel1 t_aru_tetel; -- Itt nem lehet inicializálás és NOT NULL!
v_Tetel2 t_aru_tetel;
v_Bejegyzes t_aru_bejegyzes;
-- %TYPE
v_Kod v_Tetel1.kod%TYPE := 10;
v_Kolcsonzes t_kolcsonzes_rec;
/* Függvény, ami rekordot ad vissza */
FUNCTION fv(
p_Kolcsonzo v_Kolcsonzes.kolcsonzo.id%TYPE,
p_Konyv v_Kolcsonzes.konyv.id%TYPE
) RETURN t_kolcsonzes_rec IS
v_Vissza t_kolcsonzes_rec;
BEGIN
v_Vissza.kolcsonzo.id := p_Kolcsonzo;
v_Vissza.konyv.id := p_Konyv;
RETURN v_Vissza;
END;
BEGIN
/* Hivatkozás rekord mezőjére minősítéssel */
v_Tetel1.kod := 1;
v_Tetel1.nev := 'alma';
v_Tetel1.nev := INITCAP(v_Tetel1.nev);
v_Kolcsonzes.konyv.id := fv(10, 15).konyv.id;
/* Megengedett az értékadás azonos típusok esetén. */
v_Tetel2 := v_Tetel1;
/* A szerkezeti egyezőség nem elég értékadásnál */
-- v_Bejegyzes := v_Tetel1; -- Hibás értékadás
/* Rekordok egyenlőségének összehasonlítása és NULL tesztelése
nem lehetséges */
/* A következő IF feltétele hibás
IF v_Tetel1 IS NULL
OR v_Tetel1 = v_Tetel2
OR v_Tetel1 <> v_Tetel2 THEN
NULL;
END IF;
*/
END;
/