Mit Hilfe der PL/SQL-Pakete (Packages) führt man Funktionen und Prozeduren sowie weitere PL/SQL-Elemente zu großen modularen Strukturen zusammen. Einige der vorhandenen PL/SQL-Pakete sind Ihnen bereits in den zurückliegenden Erläuterungen begegnet. Sie haben dabei gesehen, dass sie Prozeduren genauso wie Funktionen enthalten und dass man diesen Modulen Werte übergeben kann, um überaus interessante und nützliche Ergebnisse schnell und unkompliziert zu erhalten. Dies ist das Grundprinzip des objektorientierten Designs und der modernen Software-Entwicklung, wenn auch PL/SQL selbst nicht vollständig objektorientiert ist. Dies mag sich irgendwann ändern, aber bis jetzt und auch noch in der nächsten Zeit kann man ähnliche Entwicklungsmuster über den Einsatz von Paketen erreichen.
Ein Paket ist also eine abgeschlossene Einheit von Prozeduren und Funktionen, die unter einem gemeinsamen Namen zusammengefasst werden. Dabei bieten sie in ihrer Gesamtheit Werkzeuge für unterschiedliche Einsätze innerhalb eines durch die Paket-Struktur bzw. seinen Namen und/oder eine Bedeutung abgegrenzten Bereichs innerhalb der Software an. In dem Ihnen schon bekannten Paket UTL_FILE befinden sich verschiedene Werkzeuge für das Erzeugen von Dateihandles, das Öffnen und Schließen sowie natürlich das Verarbeiten (Lesen und Schreiben) von Textdateien. Neben den gerade erwähnten Prozeduren und Funktionen lassen sich allerdings auch Cursor, Variablen, Ausnahmen, Sammlungen und Datensatztypen innerhalb von Paketen speichern. Dies eröffnet beispielsweise die Möglichkeit, Sammlungen zwischen Modulen und der aufrufenden Umgebung auszutauschen, wie wir es in einem der zurückliegenden Abschnitte mit Hilfe eines anonymen Blocks realisiert hatten, indem wir in seinem Deklarationsabschnitt den benötigten Sammlungstyp deklarierten.
Die Syntax für die Erstellung eigener Pakete und die Notation, um fremde bzw. eingebaute Pakete in Anwendungen einzusetzen, ist relativ simpel und im Gegensatz zu vielen anderen Strukturen überaus leicht verständlich. Letztendlich fassen Pakete tatsächlich nur andere Sprachelemente zu einer Gruppe zusammen und bieten sie unter einem gemeinsamen Namen an. Interessant dagegen und lohnenswert für Diskussionen und Planungsgedanken ist die korrekte Umsetzung von Software-Anforderungen und die Lösung von Schnittstellenproblemen bei der Entwicklung eigener Pakete. Dies hat allerdings wenig mit der Syntax gemein, sondern lässt sich nur durch allgemeine Regeln der Software-Technik und der eigenen Erfahrung meistern.
Die Vorteile, die sich durch einen konsequenten Einsatz der Pakete (sowie aller weiteren modularen Strukturen) für die Entwicklung, Wartung und Bereitstellung von Software(-Komponenten) bieten, lassen sich im direkten Vergleich zum OOP-Ansatz folgendermaßen darstellen:
Ein Paket besteht aus zwei Bereichen, die bei der Erstellung eines gesamten Pakets unabhängig voneinander programmiert und kompiliert werden müssen. Dies ist ein deutlich anderes Vorgehen als bei den modularen Strukturen von Funktionen und Prozeduren.
Es handelt sich dabei um folgende zwei Bereiche:
CREATE [OR REPLACE] PACKAGE package_name
[AUTHID {CURRENT_USER | DEFINER}]
{IS | AS}
[PRAGMA SERIALLY_REUSABLE;]
[collection_typ_definition ...]
[record_typ_definition ...]
[subtype_definition ...]
[collection_deklaration...]
[constant_deklaration...]
[exception_deklaration...]
[object_deklaration...]
[record_deklaration...]
[variable_deklaration...]
[cursor_spezifikation ...]
[function_spezifikation...]
[procedure_spezifikation...]
[call_spec ...]
[PRAGMA RESTRICT_REFERENCES(assertions) ...]
END [package_name];
[CREATE [OR REPLACE] PACKAGE BODY package_name
{IS | AS}
[PRAGMA SERIALLY_REUSABLE;]
[collection_typ_definition ...]
[record_typ_definition ...]
[subtype_definition ...]
[collection_deklaration...]
[constant_deklaration...]
[exception_deklaration...]
[object_deklaration ...]
[record_deklaration...]
[variable_deklaration ...]
[cursor_body ...]
[function_spezifikation...]
[procedure_spezifikation...]
[call_ spezifikation...]
[BEGIN
anweisungen]
END [package_name];]
Die Abbildung illustriert die zuvor erwähnte Struktur von Paketen noch einmal, wobei auf zwei Punkte Wert gelegt wurde: Zum einen erkennt man, dass eine Anwendung, die ebenfalls wie das gesamte Paket in der Datenbank gespeichert ist, lediglich den öffentlichen Teil und damit die Paket-Spezifikation aufruft. Zum anderen erkennt man, dass beide Bereiche des Pakets unabhängig voneinander in der Datenbank gespeichert sind.

Aus der Separation der Paketstruktur in die beiden Bereiche Spezifikation und Körper ergibt sich gleichermaßen die Aufteilung in die beiden Dimensionen öffentlich (Spezifikation) und privat (Körper). Elemente in der Spezifikation lassen sich also von außerhalb aufrufen. Dies gilt für Module genauso wie für Variablen oder Konstanten. Aus Sicht der aufrufenden Umgebung endet die Sichtbarkeit also bei den Elementen der Spezifikation. Es ist daher nicht möglich (Kapselung), auf Module oder Variablen innerhalb des Pakets bzw. im Körper zuzugreifen. Für die Elemente innerhalb der Spezifikation ergibt sich ein anderer Sichtbarkeitsbereich. Sie können sehr wohl auf Elemente zurückgreifen, die lediglich im Paket-Körper definiert wurden. Dies geschieht dann entweder über Wertzuweisungen oder in den Deklarationsabschnitten von Modulen im Körper. Dass die Elemente innerhalb des Körpers ohnehin gegenseitig sichtbar sind bzw. den allgemeinen Sichtbarkeitsregelungen für Blöcke unterworfen sind, versteht sich vermutlich von selbst.
Die Abbildung soll dies noch einmal bildhaft darstellen. Auf der einen Seite erfolgt ein Aufruf durch eine Umgebung, und auf der anderen Seite liegen unterschiedliche Elemente sowohl in der Spezifikation als öffentliche Elemente wie auch im Körper als private Elemente vor. Während die aufrufende Umgebung sehr wohl auf die Elemente mit dem Suffix 1 zugreifen kann, so kann sie keinesfalls auf die Elemente mit dem Suffix 2 zugreifen. Dies ist nur den Elementen selbst gestattet sowie natürlich auch den Elementen im Körper. Die beiden Suffixe kennzeichnen dabei die beiden Sichtbarkeitsbereiche, die sich durch die Paketstruktur ergeben.

Somit bildet die Spezifikation mit ihren Elementen die Schnittstelle zwischen der aufrufenden Anwendung und dem Paket. Dieser Bereich der Schnittstellenplanung bezieht sich ausschließlich auf die Zugriffserlaubnis der im Paket vorhandenen Elemente. Für die Hemisphäre der Datenstrukturen jedoch gelten die Schnittstellen der einzelnen Elemente, da sie wiederum Werte empfangen oder auswerfen, die für die Verarbeitung innerhalb der Module (im Körper des Pakets) erforderlich sind oder die für die Verarbeitung außerhalb des Pakets in der aufrufenden Umgebung benötigt werden.
comelio.com


