Arbeiten mit Arrays in SQL, PL/SQL und Application Express: Teil II
Erscheinungsmonat |
APEX-Version |
Datenbankversion |
Oktober 2013 |
alle |
ab 10.2 |
Die Arbeit mit Arrays ist für einen APEX oder PL/SQL Entwickler alltäglich - sie
werden immer wieder gebraucht. Und doch erscheint der Umgang mit Arrays in der Oracle-Datenbank
oft rätselhaft.
Es gibt
drei Array-Typen in der Oracle-Datenbank:
VARRAYs, Nested Tables und PL/SQL Assoziative Arrays.
Dieser Tipp gibt einen Einblick in die Arbeit mit Arrays in der Oracle Datenbank und stellt vor, was geht und was nicht.
In APEX können Arrays überall genutzt werden, wo PL/SQL oder SQL zum Einsatz kommt: Beispiele sind Berichts-SQL oder PL/SQL in einem onSubmit-Prozess.
Im ersten Teil des Tipps sind
VARRAYs und Nested Tables,
die sowohl in SQL als auch in PL/SQL bereitstehen, vorgestellt worden. Die nur in
PL/SQL-Programmen verfügbaren
assoziativen Arrays werden in diesem Community Tipp behandelt.
Assoziative Arrays (PL/SQL INDEX BY-Tables)
Ein assoziatives Array wird in einem PL/SQL Block zunächst als "type" erzeugt; anschließend
kann eine Variable dieses Typs deklariert werden. Das Zuweisen von Werten geschieht danach
mit der gleichen Syntax wie bei den im
letzten Teil vorgestellten VARRAYs (allerdings ist - im Gegensatz zu diesen - keinerlei Initialisierung nötig). Der folgende
Code erzeugt beispielhaft ein assoziatives Array und weist drei Werte zu.
Weist man einer Indexposition erneut einen Wert zu, so wird der alte überschrieben.
Als Datentypen für den Index können Sie BINARY_INTEGER, PLS_INTEGER oder SIMPLE_INTEGER
verwenden (NUMBER geht nicht). Neben diesen numerischen Typen sind aber auch VARCHAR2-Werte möglich.
Etwas sonderbar verhält sich SQL NULL, verwendet
man es als Indexwert. Zuweisungen sind möglich - und mit SQL NULL kann ein Wert auch
wieder angerufen werden. Der folgende Code läuft fehlerfrei.
Verwendet man jedoch die von PL/SQL bereitgestellten Array-Methoden wie COUNT,
NEXT, LAST oder FIRST, so löst die Verwendung von SQL NULL eine Fehlermeldung aus.
Als 'Best Practice' lässt sich daher festhalten, dass man SQL NULL
nicht als Indexwert verwenden sollte.
Assoziative Arrays: Zugriff auf nicht vorhandene Indexpositionen
Besonders beachtenswert ist das Verhalten, wenn man eine Arrayposition anspricht, die es nicht gibt.
Der ausgelöste ORA-01403: no data found ist für viele verwirrend, denn man kennt den
Fehler ansonsten nur von SELECT INTO-Anweisungen. Fehler werden daher
oft an der falschen Stelle gesucht. Hier verhält sich ein assoziatives Array anders
als VARRAYs oder NESTED TABLEs.
- Wird bei einem VARRAY oder einer NESTED TABLE eine ungültige Position ("über" der Arraygröße)
angesprochen, so wird ORA-06533: Subscript beyond count
ausgelöst.
- Wird bei einem VARRAY oder einer NESTED TABLE eine gültige Position
angesprochen, deren Wert jedoch nicht belegt ist, so wird SQL NULL zurückgegeben.
Beim Zugriff auf eine PL/SQL INDEX BY Table
muss man sich also immer vor Augen halten, dass Arraypositionen nicht belegt sein könnten.
Daher ist, möchte man das Array komplett auslesen, eine einfache FOR-Schleife nicht
der richtige Weg: Man muss daher anders vorgehen und die PL/SQL-Methoden
FIRST und NEXT bzw. LAST und PRIOR verwenden.
Assoziative Arrays: Nur in PL/SQL, nicht in SQL
Da assoziative Arrays nur in PL/SQL verwendet werden können, scheidet die Übergabe
nach SQL, bspw. durch Aufrufen einer PL/SQL Funktion aus einer SQL-Abfrage, völlig
aus.
Möchte man also aus einer PL/SQL-Funktion ein Array zurückgeben und diese Funktion in
einer SQL-Anweisung verwenden, kann man nicht mit assoziativen Arrays arbeiten. Dann
kommen nur Nested Tables oder
VARRAYs in Frage - und der Datentyp muss mit CREATE TYPE direkt auf SQL-Ebene erzeugt werden.
Assoziative Arrays als Implementierungsvariante für Lookup-Tabellen
Assoziative Arrays eignen sich recht gut zur Verwaltung von Lookup-Informationen. Wenn
im Rahmen eines PL/SQL-Programms sehr häufig in eine kleine Tabelle hineingesehen
werden muss, kann es sinnvoll sein, diese in einem assoziativen Array zwischenzuspeichern. Zum
Befüllen aus einer Tabelle eignet sich die BULK COLLECT-Klausel, welche eine ganze Ergebnismengenspalte
auf einmal in das assoziative Array übernimmt.
Das folgende Codebeispiel illustriert das:
Die Spalten OWNER, OBJECT_NAME und OBJECT_TYPE der Dictionary View ALL_OBJECTS werden in
assoziative Arrays geladen. Anschließend wird ein neues assoziatives Array generiert, welches
OWNER.OBJECT_NAME als Index und OBJECT_TYPE als Wert enthält. Darin können nun Lookups
durchgeführt werden.
Misst man für die einzelnen Schritte noch die Zeit, so ergibt sich für knapp
67.000 Einträge in ALL_OBJECTS folgendes:
Die meiste Zeit wird beim initialen Selektieren der Tabelleninhalte in die
drei Arrays l_arrayowner, l_arrayname und l_arraytype verbraucht. Das "Umkopieren"
in ein neues Array geht dagegen sehr schnell. Und die Lookups selbst sind pfeilschnell:
100.000 Lookup-Operationen verbrauchen gerade einmal 2/100 Sekunden. Führt man diese
100.000 Lookups dagegen "traditionell" per SELECT INTO durch ...
Man sieht, dass sich der Aufwand in diesem Falle knapp gelohnt hätte - je öfter
die Lookup-Operation stattfindet, desto eher lohnt sich das Vorhalten des
assoziativen Arrays. Natürlich hat das Erstellen des Arrays auch einen Preis: Im
Test hat Oracle für die Arrays insgesamt etwa 16,2MB Hauptspeicher (PGA) allokiert.
Assoziative Arrays in APEX
APEX verwendet assoziative Arrays sehr oft - leider liefert ein
reines DESCRIBE der Packages nicht immer genügend Information. Welchen
Typ muss eine Variable haben, damit man APEX_UTIL.TABLE_TO_STRING damit
aufrufen kann ...?
Einerseits kann man in die Dokumentation schauen, manchmal
fehlt diese jedoch oder man hat gerade keinen Zugriff. In solchen
Fällen kann ein Blick in die Dictionary View USER_ARGUMENTS helfen.
Die Funktion kann also wie folgt genutzt werden:
Analoges gilt für die G_FXX-Arrays, mit deren Hilfe man
tabellarische Formulare mit manuellem PL/SQL Code verarbeiten
kann.
Fazit und weitere Informationen
Die Oracle-Datenbank bietet mehrere Möglichkeiten an, mit Arrays zu arbeiten.
VARRAYs und Nested Tables erlauben es, Arrays im SQL-Kontext zu nutzen.
Es wird möglich, Arrays in einzelnen Tabellenspalten
abzulegen und mit SQL auf diese Werte zuzugreifen. Insbesondere, wenn Wertelisten
stets als Ganzes gelesen und geschrieben
werden sollen, kann das VARRAY eine Alternative zu einer separaten Tabelle sein.
VARRAYs und Nested Tables lassen sich
auch in PL/SQL nutzen. PL/SQL Entwickler können jedoch auch mit assoziativen Arrays
arbeiten: diese stehen nur in PL/SQL zur Verfügung und funktionieren im Detail etwas
anders. Welche Variante man wann einsetzt, ist sicherlich von Fall zu Fall unterschiedlich
zu entscheiden.
Zurück zur Community-Seite
|