Hatáskör és élettartam

A PL/SQL a statikus hatáskörkezelést alkalmazza, de egy lokális név csak a deklarációjától kezdve látszik. Egy adott programegységben deklarált név a tartalmazott programegységekben globális névként jelenik meg és újradeklarálás esetén minősítéssel hivatkozható. A minősítő az alprogram vagy csomag neve, illetve a blokk címkéje lehet. Ha tartalmazott programegységben nem deklarálunk újra egy globális nevet, akkor az minősítés nélkül hivatkozható.

A PL/SQL-ben tehát minden nevet az előtt kell deklarálni, mielőtt hivatkoznánk rá. Alprogramok esetén viszont előfordulhat a kölcsönös rekurzív hívás. Ennek kezelésére a PL/SQL az alprogramoknál ismeri az előrehivatkozás lehetőségét. Ahhoz, hogy alprogramot hívni tudjunk, elég a specifikációját ismernünk. Az előrehivatkozás úgy néz ki, hogy csak az alprogram specifikációját adjuk meg egy pontosvesszővel lezárva, az alprogram teljes deklarációja ugyanezen deklarációs részben csak később következik.

A PL/SQL a dinamikus élettartam-kezelést alkalmazza blokkokra és alprogramokra. Egy változó akkor kap címkomponenst, ha aktivizálódik az a programegység, amelynek ő lokális változója. Ekkor történik meg az automatikus vagy explicit kezdőértékadás. A címkomponens megszűnik, ha a programegység befejezi a működését.

Nevesített konstansok inicializálása is mindig megtörténik, ha aktivizálódik az a blokk vagy alprogram, amelyben deklaráltuk őket.

1. példa

<<blokk>>
DECLARE
  i NUMBER := 1;
  p VARCHAR2(10) := 'Hello';
  /* Az alprogramban deklarált i elfedi a globális változót
  p paraméter is elfedi a külső p változót */
  PROCEDURE alprg1(p NUMBER DEFAULT 22) IS
    i NUMBER := 2;
    /* A lokális alprogram további névütközéseket tartalmaz. */
    PROCEDURE alprg2(p NUMBER DEFAULT 555) IS
      i NUMBER := 3;
    BEGIN
      /* A következő utasítások szemléltetik a minősített nevek használatát.
    A minősítések közül egyedül a 3. utasítás alprg2.p minősítése
    felesleges (de megengedett). */
    FOR i IN 4..4 LOOP
      DBMS_OUTPUT.PUT_LINE(blokk.i || ', ' || blokk.p);
      DBMS_OUTPUT.PUT_LINE(alprg1.i || ', ' || alprg1.p);
      DBMS_OUTPUT.PUT_LINE(alprg2.i || ', ' || alprg2.p);
      DBMS_OUTPUT.PUT_LINE(i || ', ' || p);
    END LOOP;
  END alprg2;
  BEGIN
    alprg2;
  END alprg1;
BEGIN
  alprg1;
END blokk;
/

/*
Eredmény:
1, Hello
2, 22
3, 555
4, 555

A PL/SQL eljárás sikeresen befejeződött.
*/

2. példa

/* Kölcsönös hivatkozás */
DECLARE
  PROCEDURE elj1(p NUMBER);
  PROCEDURE elj2(p NUMBER) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('elj2: ' || p);
    elj1(p+1);
  END elj2;
  PROCEDURE elj1(p NUMBER) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('elj1: ' || p);
    IF p = 0 THEN
      elj2(p+1);
    END IF;
  END elj1;
BEGIN
  elj1(0);
END;
/

/*
Eredmény:
elj1: 0
elj2: 1
elj1: 2

A PL/SQL eljárás sikeresen befejeződött.
*/

3. példa

DECLARE
  i number;
  /* p és j inicializálása minden híváskor megtörténik. */
  PROCEDURE alprg(p NUMBER DEFAULT 2*(-i)) IS
    j NUMBER := i*3;
  BEGIN
    DBMS_OUTPUT.PUT_LINE(' '|| i || ' ' || p || ' ' || j);
  END alprg;
BEGIN
  DBMS_OUTPUT.PUT_LINE(' i  p  j');
  DBMS_OUTPUT.PUT_LINE('-- -- --');
  i := 1;
  alprg;
  i := 2;
  alprg;
END;
/

/*
Eredmény:
 i  p  j
-- -- --
 1 –2  3
 2 -4  6

A PL/SQL eljárás sikeresen befejeződött.
*/