Qualified Expressions in Records und Associative Arrays in Oracle 18c

01.
Mai
2019
Veröffentlicht von: Hildegard Asenbauer

Records sind in PL/SQL geläufiger als Objekttypen. Nur das Handling war bisweilen etwas mühsam, da jedes Feld einzeln zugewiesen werden musste. Da wünschte man sich doch gelegentlich etwas Analoges zum Konstruktor bei Objekttypen. Mit Version 18c geht dieser Wunsch nun in Erfüllung. :)

Qualified Expressions

Sogenannte Qualified Expressions sind Ausdrücke, die einer nicht-skalaren Variable in einem Schritt mehr als einen Wert zuweisen. Was es für Objekttypen und andere Arten von Collections schon immer gab (hier Konstruktoraufruf genannt), gibt es jetzt also auch für Records und Associative Arrays. Nur hier eben unter dem Begriff „Qualified Expressions“. Und statt von einem Konstruktor spricht man hier von „Typemark“; dahinter verbirgt sich nichts anderes als die – erforderliche - explizite Angabe des Datentyps. Im Gegensatz zum Konstruktor ist die Verwendung aber ein „Kann“, kein „Muss“.

Records

Jeder kennt ein solches oder ähnliches Konstrukt, oft noch mit viel mehr Feldern:

DECLARE
   TYPE t_data_rec IS RECORD
    (name      VARCHAR2 (50 CHAR),
     vorname   VARCHAR2 (50 CHAR),
     geb_dat   DATE
   );

   v_data_1   t_data_rec;
   v_data_2   t_data_rec;
   v_data_3   t_data_rec; 
BEGIN
   v_data_1.name     := 'Mustermann';
   v_data_1.vorname  := 'Max';
   v_data_1.geb_dat  := TO_DATE ('01.01.1970');

   v_data_2.name     := 'Müller';
   v_data_2.vorname  := 'Sofia';
   v_data_2.geb_dat  := TO_DATE ('14.11.1987');

   v_data_3.name     := 'Meier';  
   v_data_3.geb_dat  := TO_DATE ('14.11.1987');
END;
/

Das war bisher die einzige Methode, wie die Felder eines Records befüllt werden können.

In Version 18c nun wird Entwicklern die Arbeit erleichtert. Man kann jetzt auch alle Felder - oder einen Teil davon - mit einem einzigen Aufruf befüllen. Und man hat alle Freiheiten dabei: Man kann, je nach persönlicher Präferenz, sowohl positionale als auch namentliche Notation verwenden, wie man das von Prozeduraufrufen kennt:

DECLARE
   TYPE t_data_rec IS RECORD
    (name      VARCHAR2 (50 CHAR),
     vorname   VARCHAR2 (50 CHAR),
     geb_dat   DATE
   );

   v_data_1   t_data_rec;
   v_data_2   t_data_rec;
   v_data_3   t_data_rec;  
BEGIN
   v_data_1 :=  t_data_rec('Mustermann', 'Max', TO_DATE ('01.01.1970'));
  
   v_data_2 := t_data_rec(name     => 'Müller',
                          vorname  => 'Sofia',
                          geb_dat  => TO_DATE ('14.11.1987'));

   v_data_3 :=  t_data_rec('Meier', geb_dat => TO_DATE ('17.03.2018'));
END;
/

Analog zu einem Konstruktoraufruf handelt es sich bei einer Qualified Expression um eine (Re-) Initialisierung einer Variablen. Das heißt, ein erneuter Aufruf löscht alle bisherigen Feldwerte des Records. Das gilt natürlich auch dann, wenn ein bisher belegtes Feld im zweiten Aufruf nicht mitgegeben wird:

SET SERVEROUTPUT ON
DECLARE
   TYPE t_data_rec IS RECORD
    (name      VARCHAR2 (50 CHAR),
     vorname   VARCHAR2 (50 CHAR),
     geb_dat   DATE
   );

   v_data_1   t_data_rec;
BEGIN
   v_data_1 :=  t_data_rec('Mustermann', 'Max', TO_DATE ('01.01.1970'));

   v_data_1.name := 'Meier';                   -- Überschreiben dieses einen Wertes
  
   DBMS_OUTPUT.PUT_LINE('Vorname: '||v_data_1.vorname);

   v_data_1 :=  t_data_rec(name => 'Meier');   -- Re-Initialisierung
  
   DBMS_OUTPUT.PUT_LINE('Vorname: '||v_data_1.vorname);
END;
/
Vorname: Max
Vorname:

Associative Arrays

Bei Nested Tables und Varrays kennt man es schon lange, dass man das Array im Zuge der Initialisierung auch gleich befüllen kann. Nur beim dritten Collection-Typ, den Associative Arrays, muss jedes Element einzeln befüllt werden (abgesehen natürlich von Bulk Binds).

DECLARE
   TYPE t_num_tab IS TABLE OF NUMBER;
   TYPE t_v_tab IS VARRAY (2000) OF VARCHAR2 (200);  
   TYPE t_num_tab_aa IS TABLE OF NUMBER INDEX BY PLS_INTEGER;

   v_num_tab     t_num_tab;
   v_v_tab       t_v_tab;  
   v_num_tab_aa  t_num_tab_aa;
BEGIN
   v_num_tab  :=  t_num_tab (1, 2, 3, 4, 5);
   v_v_tab    := t_v_tab ('Armin', 'Bodo', 'Caesar', 'Dieter');

   v_num_tab_aa(1) := 15;
   v_num_tab_aa(2) := 16;
   v_num_tab_aa(3) := 17;
   v_num_tab_aa(7) := 18;
   v_num_tab_aa(9) := 19;
END;

Für Associative Arrays wurden nun ebenfalls Qualified Expressions eingeführt. Hier spricht man, analog wie bei den Records, wieder von Typemark statt von Konstruktor. So können auch hier in einem einzigen Aufruf beliebig viele Werte zugeordnet werden:

DECLARE 
   TYPE t_num_tab_aa IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
   TYPE t_num_tab_idxv IS TABLE OF NUMBER INDEX BY VARCHAR2(10);
 
   v_num_tab_aa t_num_tab_aa;
  
   v_num_tab_idxv t_num_tab_idxv;  
BEGIN
   v_num_tab_aa := t_num_tab_aa(1 => 15,
                                 2 => 16,
                                 3 => 17,
                                 7 => 18,
                                 9 => 19
                                 );


  
   v_num_tab_idxv := t_num_tab_idxv('eins'   => 15,
                                    'zwei'   => 16,
                                    'drei'   => 17,
                                    'vier'   => 18,
                                    'sieben' => 19
                                    );
END; 

Der Index muss allerdings auch bei einem numerischen Index zwingend explizit angegeben werden; eine einem Konstruktoraufruf analoge positionale Syntax führt zu einem Fehler:

PLS-00681: Benannte Verknüpfungssyntax ist erforderlich

Auch hier bedeutet ein erneuter Aufruf eine Re-Initialisierung und damit den Verlust aller bisherigen Einträge im Array. Einträge können natürlich jederzeit in der gewohnten Syntax ergänzt oder überschrieben werden.


Fazit

Bei Records stellt diese kleine aber feine Neuerung eine echte Erleichterung dar. Entwickler werden das Feature lieben. Bei Collections dagegen wird wegen der Art des Einsatzes solcher Variablen (bevorzugt bei Bulk Binds und in Schleifen) und der auch bisher schon gegebenen Auswahlmöglichkeit zwischen den einzelnen Typen der Gebrauch wohl begrenzt sein.

PL/SQL Oracle 18c

Jede Menge Know-how für Sie!

In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.