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“.
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:
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.
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.
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.