# Einleitung
## Wer braucht das Buch?

Dieses Buch wendet sich an Einsteiger in die PL/SQL-Programmierung und an Anwender in der Form eines Nachschlagewerkes. Grundlegende Kenntnisse der Programmierung, des Aufbaues von relationalen Datenbanken und SQL werden für das Verständnis des Buches vorausgesetzt.

## Architektur des Buches

Im ersten Teil des Buches wird die Methode der Syntaxbeschreibung für die PL/SQL-Grammatik, im zweiten Teil die Syntax der PL/SQL-Sprachelemente und im dritten Teil die Anwendung der wichtigsten PL/SQL-Systembibliotheken erläutert. Zu jedem PL/SQL-Element gibt es neben der Syntaxbeschreibung ein kurzes Codebeispiel. Diese Beispiele stellen keine funktionsfähigen Programme dar, sondern nur die Umsetzung der Syntaxbeschreibung in Programmcode. Im letzten Teil werden programmtechnische Aspekte behandelt. Dazu werden mit ausgewählten Systembibliotheken Anwendungsbeispiele erstellt und auf die Verbindung mit anderen Programmiersprachen eingegangen.

## Wie funktioniert PL/SQL

PL/SQL steht für Procedural Language/SQL, ist eine prozedurale Programmiersprache und erweitert die Abfragesprache SQL. Mit PL/SQL kann ausschließlich in Oracle Datenbanken gearbeitet werden, unabhängig vom verwendeten Betriebssystem. Die Übertragung in andere Datenbanksysteme, die Programmierung erlauben, ist ohne manuelle Nacharbeit nicht möglich. Ähnliche Programmiermöglichkeiten gibt es unter anderem in folgenden Datenbanksystemen.
* PL/pgSQL in der Open-Source-Datenbank PostgreSQL
* SQL PL für DB2
Der Programmcode wird in einer Datenbanktabelle des Datadictionary in lesbarere Textform gespeichert. Es besteht die Möglichkeit, den Quellcode in ein internes Format umzuwandeln. Dieses Umwandlung wird über den PL/SQL-Wrapper durchgeführt. Der Programmcode wird interpretativ abgearbeitet, das kann sowohl auf der Serverseite innerhalb der Datenbank, als auch auf der Clientseite in der von Oracle zur Verfügung gestellte Oberfläche Oracle Forms erfolgen. Jeder Benutzer der Datenbank hat eine eigene Session. Innerhalb dieser Session läuft für den Benutzer die Interpretation des Programmcodes ab. Der konkrete Ablauf wird im Abschnitt Programmentwicklung erläutert.

# Grundlegende Elemente
## Wer ist Herr Backus?

Für die Beschreibung einer Programmiersprache gibt es verschiedene Möglichkeiten. Grundlegend unterscheidet man zwischen grafischer und verbaler (Metasprache) Beschreibung. In diesem Buch verwende ich eine Metasprache, die der Erweiterten Backus-Naur-Form (EBNF) entspricht. Diese Metasprache geht auf John Warner Backus und Peter Naur zurück. Die EBNF verwendet folgende Elemente zur Darstellung
| Verwendung | Darstellung |
| Definition eines Elementes | = |
| implizite Aufzählung einer bekannten, ordinalen Menge | .. |
| alternatives Element | | |
| optionales Element | [ ] |
| optionale Wiederholung des letzten Elementes | [..] |
| Elementgruppierung | ( ) |
| Wiederholung der Elementgruppierung | (..) |
| optionale Wiederholung der Elementgruppierung | [(..)] |
| Regelende | ; |
| konstantes Element (Begrenzung) | " " |

## Namen, Zahlen und Co.

Jede Programmiersprache besteht aus elementaren, nicht mehr teilbaren, Bestandteilen, die als lexikalische Elemente bezeichnet werden.
* Namen
* Zahlen
* Schlüsselworte
* Operatoren
* Kommentare

### Namen

Mit einem Namen wird eine Deklaration, die einen Typ, eine Variable in unterschiedlicher Ausprägung oder eine Funktionalität bezeichnet, definiert. Der Name hat folgende Struktur:
Ein Name beginnt immer mit einem Buchstaben und ist mindestens ein Zeichen lang. Damit wären aber nur 26 Namen möglich, da in PL/SQL die Groß-/Kleinschreibung keine Rolle spielt. Dem ersten Buchstaben dürfen weitere Buchstaben, Ziffern oder das Sonderzeichen "_" folgen. Ein Name darf maximal 30 Zeichen lang sein und muss ein Unikat innerhalb seines Gültigkeitsbereiches sein.

### Zahlen

Zahlen werden als Konstanten innerhalb von Anweisungen oder bei Deklarationen verwendet und haben folgende Struktur:
Eine Zahl kann mit einem Vorzeichen beginne, fehlt es, wird das positive Vorzeichen angenommen. Ganze Zahlen bestehen aus mindestens einer Ziffer. Reelle Zahlen bestehen aus Vorkomma- und Nachkommastellen, die durch einen Punkt getrennt werden, wobei mindestens ein Teil vorhanden sein und dieser Teil aus mindestens einer Ziffer bestehen muss. Über die Genauigkeit und die Typumwandlung wird im Abschnitt Vereinbarungen ausführlich eingegangen. Reelle Zahlen können auch in wissenschaftlicher Darstellung, in Exponentialform, geschrieben werden

### Konstanten

Mit Konstanten werden Werte festgelegt, die in Ausdrücken verarbeitet werden.
Der Zeichenkettenbegrenzer ist das Zeichen ", deshalb wird es in sich selbst in der Regel dargestellt.

### Schlüsselworte

Fest vorgegebene Zeichenketten in einer Programmzeile werden als Schlüsselworte bezeichnet.
Schlüsselworte sind reservierte Worte und dürfen nicht als Namen verwendet werden. Im Anhang befindet sich eine Auflistung aller Schlüsselwort in PL/SQL.

## Was ist NULL?

Verschiedene Programmiersprachen, dazu zählt PL/SQL, besitzen die Möglichkeit, den Zustand, dass eine Variable definiert, aber nicht mit einem Wert belegt ist, auszuwerten. Dazu wird in der Variable ein bestimmtes, dem Programmierer nicht bekantes, Bitmuster hinterlegt, welches als NULL definiert ist. An dieser Stelle muss betont werden, dass NULL einen Zustand und keinen Wert darstellt. Auf den Zustand NULL kann nicht mit Vergleichsoperatoren, sondern nur mit NULL-Operatoren verglichen werden.

## Operationswerkzeuge

Mit Operationszeichen werden einzelne Operanden, das können Variablen, Konstanten oder Ausdrücke sein, verknüpft. Je nach Typ der Operanden unterscheidet man zwischen
* arithemetische,
* booleschen,
* Character-,
* Mengen-,
* Vergleichsoperationszeichen und
* NULL-Operationszeichen.

### Arithmetische Operationszeichen

Mit arithmetischen Operationszeichen werden numerische Ausdrücke verbunden.
Arithmetische Operationszeichen liefern als Ergebnis numerische Werte. Ob die mathematische Operation, die mit dem Operationszeichen verbunden ist, auch erklärt ist (z.B. Division durch 0), wird erst bei der Laufzeit erkannt. Höhere arithmetische Operationen (Winkelfunktion u.a.m.) werden durch Standardfunktionen abgebildet.

### Boolsche Operationszeichen

Mit boolschen Operationszeichen werden logische Ausdrücke verbunden.
Das Ergebnis eines logischen Ausdrucks, dessen Operanden mit "AND" verbunden sind, ist TRUE, wenn alle Operanden TRUE als Ergebnis liefern. Mit "OR" verknüpfte Operanden liefern TRUE als Ergebnis, wenn mindestens ein Operand TRUE als Ergebnis hat. "NOT" negiert das Ergebnis eines Operanden.

### Characteroperationszeichen

Mit Characteroperationszeichen werden Zeichenketten bearbeitet.
Mit diesem Operationszeichen werden zwei Zeichenketten verknüpft. Alle anderen Operationen mit Zeichenketten (Substring, InString usw.) werden durch Standardfunktionen abgebildet.

### Mengenoperationszeichen

PL/SQL kennt nur zwei Mengenoperationszeichen, die als Ergebnis der Operation TRUE oder FALSE liefern.
Mengenoperationszeichen liefern als Ergebnis boolsche Werte. "IN" liefert TRUE, wenn der Operand in der aufgezählten Menge ist. "NOT IN" kehrt die Auswertung um, der Operand darf nicht in der aufgezähten Menge sein. Mit "BETWEEN" wird ein Operand auf Zugehörigkeit, einschließlich der angegebenen Grenzen, zur aufgezählten Menge überprüft. Das Ergebnis ist TRUE, wenn er zur Menge gehört. "NOT BETWEEN" überprüft, die Nichtzugehörigkeit zur Menge und liefert TRUE für diesen Fall.

### Vergleichsoperationszeichen

Vergleichsoperatoren liefern boolsche Werte als Ergebnis. Verglichen werden können nur Operanden gleichen Typs (numerische, char usw.)
Die Operationszeichen sind selbsterklärend, außer die letzten beiden, die die Operanden auf Ungleichheit vergleichen.

### NULL-Operationszeichen

Um den Zustand NULL zu erkennen, gibt es zwei Operationszeichen,
Die Verknüpfung eines Operanden mit den NULL-Operationszeichen liefert einen boolschen Wert zurück. Die Verwendung aller anderen Operationszeichen auf einen Operanden der den Zustand NULL hat ist undefiniert.

## Wie kommentiert man? Kann man schreiben, wie man will?

Jeder Quellcode sollte nicht nur fehlerfrei sein, sondern auch verständlich. Neben der Strukturierung des Programmablaufes, dienen Kommentare dazu, den Programmablauf verständlich zu machen. PL/SQL hat zwei Möglichkeiten, Kommentare in den Quellcode einzufügen
Das Regelelement "zeilenvorschub" ist vom Betriebssystem abhängig. Eine Verschachtelung von ein- und mehrzeiligen Kommentaren ist möglich, sollte aber vermieden werden.
PL/SQL ist, im Gegensatz zu Programmiersprachen wie JAVA, nicht case-sensitiv. Der Name ABC ist identisch mit aBc. Ebenfalls ist es ohne Bedeutung,
* wieviele Leerzeichen zwischen zwei lexikalischen Elementen stehen,
* wieviele Leerzeichen am Zeilenbeginn eingerückt werden und
* wie lang die Zeile ist.
Leerzeichen werden, außer in Characterkonstanten, bei der Quelltextinterpretation ignoriert. Zur besseren Übersichtlichkeit werden alle Schlüsselworte in diesem Buch groß geschrieben. In PL/SQL wird in den meisten Fällen kommerzielle Software geschrieben. In Softwarefirmen gibt aus vielen Gründen (Programmentwicklung im Team, Wartbarkeit der Software, Qualitätssicherung u.a.m.) Vorschriften,
* wie Quelltexte zu strukturien sind,
* welche Namen zu vergeben sind,
* welche Sprachelemente nicht verwendet werden dürfen (z.B. Exceptionhandling zur Programmsteuerung) und
* wie Sprachelemente verwendet werden dürfen (z.B. keinen impliziten Cursor).
Auf diese Details kann in einem Wikibook natürlich nicht eingegangen werden, sondern nur auf die Möglichkeiten, die PL/SQL insgesamt bietet.

# Typen

PL/SQL kennt die folgenden vordefinierten Typen. Das sind Typen, deren Struktur vom Programmierer nicht mehr verändert werden kann.

## Skalare Typen

Skalare Typen haben keine weiteren, internen Strukturen, die vom Programmierer verändert werden können.

### Numerische Typen

Numerische Typen definieren ganzzahlige, reelle und numerische Aufzählungstypen unterschiedlicher Genauigkeit und Wertebereiche.

#### Binäre, ganzzahlige Typen

Die binären Typen stellen ganzzahlige Zahlen, wie der Name schon sagt, intern in binärer Form dar. Sie sind in der Berechnung besonders schnell und werden hauptsächlich als Index verwendet, wobei der Typ PLS_INTEGER am schnellsten ist. Die Subtypen dieser Typklasse unterscheiden sich nur im Wertebereich,
Wertebereiche
Der Type SIGNTYPE hat nur die drei Werte -1, 0 und 1.

#### Reelle Typen

Für reelle Typen gibt verschiedene Darstellungsmöglichkeiten, die sich grundlegend in Floatingpoint und Fixedpoint unterscheiden. Der Wertebereich geht von 10**-130 bis 10**125. Der Typ NUMBER gestattet die größte Gestaltungsmöglichkeit durch die optionale Längendefinition. Floatingpoint wird durch NUMBER ohne Längenbeschreibung definiert und Fixedpoint wird mit einer Längenbeschreibung definiert. Es gelten folgende Regeln bei der Festlegeung der Längenbeschreibung.
* nur Gesamtlänge bzw. Nachkommaanteil ist 0
Die Längendefinition ist identisch mit 0 als Nachkommaanteil und es wird nur der ganzzahlige Anteil der reellen Zahl verwendet.
* Nachkommaanteil < 0
Auch diese Variante ist möglich, obwohl sie im ersten Moment widersprüchlich ist. Mit einem negativen Wert im Nachkommaanteil werden Vorkommaanteil 0 gesetzt. -1 setzt die Einerstelle auf 0; es können also nur die Zahlen 10, 20, 30 usw. verarbeitet werden. -2 setzt die Einer- und Hunderterstelle auf 0, es können also nur die Zahlen 100, 200, 300 usw. verarbeitet werden. Damit sollte die Verwendung von negativen Werten als Nachkommaanteilen verständlich sein.
* Nachkommaanteil > 0
Mit einem Nachkommaanteil > 0 wird die Genauigkeit der reellen Zahl festgelegt. 1 als Nachkomaanteil verarbeitet nur Zehntelwerte, 2 Zehntel- und Hunderstelwert.
Bei der Längenfestlegung ist zu beachten, dass die Gesamtlänge größer als der Nachkommaanteil sein muss. Die Subtypen DEC, DECIMAL und NUMERIC definieren eine 38-stellige, reelle Zahl; DOUBLE PRECISION und FLOAT definieren eine 128 Bit und REAL eine 63 Bit lange, reelle Zahl.

#### Ganzzahlige Typen

Die Typen INTEGER, INT und SMALLINT stellen eine 38 Zeichen lange, ganze Zahl dar.

### Character-Typen

Character-Typen definieren alphanumerische Werte, auf die in ihrer Gesamtheit, aber auch auf ihre einzelnen Elemente, zugegriffen werden kann.

#### CHAR-Typen

CHAR ist ein Typ zur Speicherung, mit festgelegter Länge, von Zeichen. Die maximal mögliche Länge beträgt 32767. Mit der Festlegung der Struktur wird definiert, auf was sich die Längenangabe bezieht - auf ein Byte oder ein Zeichen. Das ist besonders wichtig, wenn mit UTF8-Codezeichen gearbeitet wird. Eine Länge von 32767 und die Struktur BYTE ermöglicht bei der Speicherung von 2-Byte-UTF8-Codezeichen nur 16383 Zeichen zu speichern. Die Standardannahme für die Länge ist 1 und als Struktur wird die Festlegung des Parameters NLS_LENGTH_SEMANTICS der benutzenden Datenbankinstanz verwendet. Der Typ CHARACTER ist identisch mit dem Typ CHAR und ist nur aus Kompatibilitätsgründen eingeführt wurden.

#### LONG-Typen

Dieser Typ hat eine konstante Länge von 32760 Bytes und dient zur Speicherung von Zeichen (LONG, LONG RAW) oder binären Daten (LONG RAW). Ab der Version Oracle 9i gibt es ((PL_SQL: LOB-Typen|LOB-Tyen)) zur Speicherung von binären Daten und Zeichen bis 2GB. , die die LONG Die Chractertypen haben unterschiedliche Bedeutung und sind teilweise auf Abwärtskompatibilität zurück zu führen.

#### RAW-Typen

Der Typ RAW ist identisch mit den Typ LONG RAW, der einzige Unterschied ist die maximale Lange von 32767 Bytes.

#### ROWID-Typen

Ein ROWID ist die eindeutige Adresse innerhalb eines Datensatzes in einer Tabelle. Jede Tabelle hat das ROWID als Pseudospalte. Es wird in physische und logische ROWIDs unterschieden, wobei der Typ ROWID nur physische ROWIDs und der Typ UROWID (universell ROWID) physische und logische ROWIDs darstellen kann. Physische ROWIDs haben folgenden Aufbau
Das Element haben folgende Längen in Byte.

#### VARCHAR2-Typen

Dieser Typ ist fast identisch mit dem CHAR-Typ. Die Länge und die Struktur (Byte oder Char) kann festgelegt werden. Der wesentliche Unterschied besteht darin, dass VARCHAR2 speicher- und performanceorientiert arbeitet und nur die tatsächlich benötigte Anzahl von Speicherplätzen belegt. CHAR hingegen belegt den Speicher immer mit der vereinbarten Länge. Die Subtypen STRING und VARCHAR sind identisch zu VARCHAR2 und existieren aus Kompatibilitätsgründen.

#### Nationale CHAR-Typen

Um erweiterte Zeichensätze, die mehr als 256 Zeichen beinhalten, zu ermöglichen. Dieses ist vorallem bei asiatischen Sprachen notwendig. Die Datenbank arbeitet mit zwei Zeichensätzen, den Datenbankzeichensatz, mit dem alle Informationen über die Strukturen und der PL/SQL-Programmcode und dem Nationalen Zeichensatz mit dem alle Informationen in den Tabellen gespeichert werden. Der Nationale Zeichensatz wird im UNI-Code dargestellt, der 1, 2 oder 3 Byte pro Zeichen lang ist. Zeichensätze, die für jedes Zeichen immer 2 Byte benötigen, werden als AL16UTF16 bezeichnet. Zeichensätze, die für jedes Zeichen 1, 2 oder 3 Byte benötigt, werden als UTF8 bezeichnet. Die Längenangaben in der Typdefinition ist in Byte, das heißt, bei Speicherung in UTF-8 ist die Anzahl der maximal möglichen Zeichen 32787/3 und bei AL16UTF16 32767/2. Der Unterschied zwischen den beiden NCHAR und NVARCHAR2 besteht darin, dass NCHAR immer den Speicherplatz laut Längenbeschreibung belegt, unabhängig davon, wieviel Speicher tatsächlich benötigt wird. NVARCHAR2 belegt nur soviel Platz, wie tatsächlich benötigt wird.

### Boolsche Typen

Dieser Typ ist sehr einfach beschrieben.

### Datums- und Zeittypen

Mit diesen Typen werden Datums- und Zeitangaben definiert. Die einzelnen Komponenten des Datums und der Zeit unterliegen folgenden Beschränkungen bzw. Wertebereichen.
Zur Darstellung von Zeitzonen sind folgende Wertebereiche möglich.
Die Region der Zeitzonen ist dem Parameter V$TIMEZONE_NAMES der aktuellen DB-Instanz zu entnehmen. Folgende Datums- und Zeittypen sind definiert.

#### Typ DATE

Dieser Typ definiert ausschließlich das Datum. Oracle kann das Datum im Bereich vom 1.1.4712 v.Chr. bis 31.12.9999 darstellen. Es besteht die Möglichkeit das Datum als Zahl der Tage seit dem Startdatum darzustellen.

#### Typ TIMESTAMP

Timestamp stellt Datum und Uhrzeit in einer rellen Zahl dar, wobei der ganzzahlige Anteil das Datum und der Nachkommaanteil die Zeit seit Mitternacht ist. der Parameter precision gibt die Genauigkeit der Sekundenanteile an, wobei 1 Zehntelsekunden, 2 Hunderstelsekunden usw, sind. Der Zusatz WITH TIME ZONE speichert das Datum in der lokalen Zeitzone mit einem Displacment in Stunden und Minuten der lokalen Zeitzone zu UTC oder den Namen der Zeitzone. Mit dem Zusatz WITH LOCAL TIME ZONE erfolgt bei Speicherung eine Umrechnung von der lokalen Zeitzone in die Zeitzone der Datenbank und dem Displacment der umgerechneten Zeit zu UTC.

#### Typ INTERVAL

Mit dem INTERVAL-Typ werden Zeitdifferenzen definiert. Der Parameter precisionYear definiert bei INTERVAL YEAR die Anzahl der Ziffern bei der Jahresangabe Der Standard ist 2, möglich ist 0. Die Differenz wird als Zeichenkette definiert, wobei Jahr und Monat getrennt, als auch zusammen festgelegt werden können. Beispiel für zeitdiff als Variable vom Typ INTERVAL YEAR (3) TO MONATH:
Der Parameter precisionDay legt die Anzahl der Ziffern bei der Tagesangabe fest, Standard ist 2 und der Parameter precisionSecond legt die Anzahl der Ziffern bei der Sekundenangabe fest, Standard ist 6. Die Zuweisung erfolgt analog wie im Beispiel bei INTERVAL YEAR TO MONTH.

## LOB-Typen

Die Abkürzung LOB steht für Large Object. Mit LOB-Typen werden, aus der Sicht von PL/SQL, unstrukturierte, binäre Daten mit einer Größe von maximal 4 Gigabyte definiert. Es kann sich dabei um
* Texte,
* Files,
* Bilder,
* Videos u.a.m.
handeln. Es handelt sich um Objekte, die, wie in der objektorientierten Programmierung, für ihre Bearbeitung Methoden haben. Die Definition eines LOB-Types stellt einen Pointer zur Verfügung, der auf den referenzierten Speicherplatz zeigt. Eine Pointerverarbeitung, wie zum Beispiel in C, ist nicht möglich; es gibt keine Möglichkeit, die Adresse an sich unter PL/SQL auszulesen und damit in Form einer Pointerarithmetik zu arbeiten. Aus der Sicht des Programmierers erfolgt der Zugriff statisch auf einen reservierten Speicherbereich. Zur Bearbeitung von LOB-Typen steht das Package DBMS_LOB zur Verfügung.

### BFILE

Mit dem LOB-Typ BFILE wird der Zugriff auf ein File aus dem Filesystem ermöglicht. Es muss gewährleistet sein, das der User, der aus der Sicht des Betriebssystem Oracle gestartet hat, auf das File lesende Zugriffsrechte hat. Es ist nur ein lesender Zugriff auf das File über den BFILE-Type möglich. Des weitren ist zu berücksichtigen, dass der BFILE-Type nicht der Transaktionssteuerung der Datenbank unterliegt. Es ist nicht möglich unbegrenzt viele Files duch die Definition von Variablen mit dem Typ BFILE in einer Session zu bearbeiten. Die maximale Anzahl wird durch den Datenbankparameter SESSION_MAX_OPEN_FILES festgelegt. Dabei muss beachtet werden, dass es noch andere Möglichkeiten gibt, Files durch die Datenbank (Package UTL_FILE) zu bearbeiten.

### BLOB

Mit dem LOB-Typ BLOB werden binäre Daten mit einer Größe von maximal 4 GB definiert. Dieser Typ unterliegt der Transaktionssteuerung.

### CLOB und NCLOB

Mit dem LOB-Typ CLOB und NCLOB werden Characterdaten mit einer Größe von maximal 4 GB definiert. Diese beiden Typen unterliegen der Transaktionssteuerung. CLOB ist auf den Typ Characters vom Typ VARCHAR und NCLOB auf Characters vom Typ NVARCHAR zurückzuführen.

### XMLType

Im Gegensatz zu den bisher betrachteten LOB-Typen handelt es sich beim LOB-Type XMLType um ein Objekt. Dieser Typ besteht aus einem Datenbereich, der das XML-Dokument enthält, sowie aus einer Vielzahl von Methoden, mit der das XML-Dokument bearbeitet werden kann. Ausführlich wird im Abschnitt XML auf die Erstellung und Verarbeitung von XML-Dokumenten eingegangen.

## Typkonvertierung

PL/SQL gestattet eine implizite Typkonvertierung über Zuweisungen. Die explizite Typkonvertierung wird über Funktionen realisiert, bei denen teilweise Formatierungsvorschriften vorgegeben werden können.

### Implizite Typkonvertierung

Implizit können folgende Typen konvertiert werden
| von/nach | Character | Number | Datetypen | Rowid |
| Character | | eingeschränkt | eingeschränkt | immer |
| Number | immer | | nein | immer |
| Date | immer | immer | | nein |
| Rowid | immer | immer | nein | |
Einschränkung
Die Umwandlung von
* Character in Number ist nur möglich, wenn es sich bei dem String um eine Zahl handelt,
* Character in Datetypen ist nur möglich, wenn der String einem Datum gemäß dem im Parameter NLS_DATE_FORMAT und NLS_DATE_LANGUAGE festgelegten Format entspricht.

### Explizite Typkonvertierung

Die explizite Typkonvertierung ist extrem komplex und hat eine Vielzahl von Parametern, die hier im Einzelnen erläutert werden sollen.

#### Konvertierung in numerische Datentypen

Die Konvertierung von Characterwerten in numerische Werte ermöglicht eine implizite Formatierung oder eine individuelle Formatsteuerung des Ausgangswertes für die Umwandlung.
Formatierungen
| Formatierungszeichen | Bedeutung | Beispiel |
| 0 | Zeichen ist eine Vornull | '0123','0999' --> 123 |
| 9 | Zeichen ist eine Ziffer | '123','999' --> 123 |
| FM | Entfernen alle Blanks und Vornullen | ' 123 ','FM999' --> 123 |
| PR | positives Vorzeichen | '+123','PR999' --> 123 |
| MI | negatives Vorzeichen | '123-','999MI' --> -123 |
| S | Vorzeichen | '+123','S999' --> 123 |
| D oder , | Dezimaltrenner | '123.1','999D9' --> 123,1 |
| G oder . | Tausendertrenner | '1.234','9G999' --> 1234 |
| $ | Währungszeichen | '123$','999$' --> 123 |
| C | internationales Währungszeichen | '123$','999C' --> 123 |
| L | lokales Währungszeichen | '123€','999L' --> 123 |
| U | Währungssymbol im DB-Parameter NLS_DUAL_CURRENCY | '123€','123U' --> 123 |
| EEEE | wissenschaftliche Notation | '1.23E+02','9.99EEEE' --> 123 |
| TM9 oder TME | minimale Textdarstellung | '123','TM9' --> 123 |
| RN oder rn | römische Zahlendarstellung (groß/klein) | 'XII','RM' --> 12 |
| V | Zehnerpotenzdarstellung | '1.23x45','9.99V99' --> 123 |
| X | hexadezimale Darstellung | 'FF','XX' --> 128 |
Die Formatierung muss die Zeichenfolge der umzuwandelnden Zeichenkette exakt beschreiben. Es erklärt sich von selbst, dass es nicht mögliche Kombinationen gibt, die hier aber nicht weiter erläutert werden sollen. Ebenso soll an dieser Stelle darauf hingewiesenw erden, dass alle Vorzeichenformatierungen nur am Anfang oder Ende der Formatbeschreibung stehen dürfen.
Der 'text' ist eine Zeichenkette, die als Währungsbezeichnung ausgegeben wird und der 'isocurrencycode' das Währungskürzel. Die Parameter überschreiben während der Ausführung der Funktion die Werte der Parameter der DB.

#### Konvertierung in Datetypen

Die Konvertierung von Characterwerten in Datetypen ermöglicht eine implizite Formatierung oder eine individuelle Formatsteuerung des Ausgangswertes für die Umwandlung.
Formatierungen
| Formatierungszeichen | Bedeutung | Beispiel |
| AD oder A.D. | | |
| AM oder A.M. | | |
| BC oder B.C. | | |
| CC oder BCC | Jahrhundert zweistellig | 1999,'CC' --> 20 |
| Q | Quartal | 10.05.2012,'Q' --> 2 |
| YYYY oder YEAR | Jahr vierstellig | 1999,'YYYY' --> 1999 |
| YYY | Jahr dreistellig | 1999,'YYY' --> 999 |
| YY | Jahr zweistellig | 1999,'YY' --> 99 |
| Y | Jahr einstellig | 1999,'Y' --> 9 |
| SYYYY oder SYEAR | Jahr mit Vorzeichen | 1999,'SYYYY' --> 1999 |
| Y,YYY | Jahr mit Tausendertrenner | 1999,'Y,YYY' --> 1,999 |
| MM | Monat zweistellig | 10,'MM' --> 10 |
| MON | Monat dreibuchstabig | 1,'MON' --> JAN |
| MONTH | Monat mit 9 Characters (rechts Blanks) | 1,'MONTH' --> Januar |
| RM | Monat in römischen Zahlen | 10,'RM' --> X |
| W | Woche im Monat | |
| WW | Woche im Jahr | |
| IW | Industriewoche im Jahr | |
| D | Tag in der Woche | |
| DD | Tag im Monat | |
| DDD | Tag im Jahr | |
| DAY | Wochentag mit 9 Characters (rechts Blanks) | |
| DY | Tag dreibuchstabig | |

## Die Typen aus der Datenbank

Es ist in PL/SQL möglich, Typen auf
* Tabellen und Views,
** in der Gesamtheit der Tabellen- oder Viewstruktur oder
** eines einzelnen Spaltenelementes (ordinale Typdefinition in Bezug auf den Typ der Spalte),
* Typdefinitionen in Packages und
* Typdefinitionen in der DB
zurückzuführen. Der Vorteil dieser Art der Typzuweisung ist, dass die Programmstruktur sofort invalid wird, wenn das Datenbankobjekt geändert wird. Dadurch werden potentielle Fehlerquellen, die durch Strukturänderungen der Tabellen oder Views entstehen, vermieden.

## Den eigenen Wunschrecord festlegen

Neben Strukturdefinitionen, die auf Tabellen oder Views zurückgeführt werden, kann ein freier Record als Typ definiert werden. Diese Art der Typdefinition kann beliebige viele, auch weitere Recorddefinitionen enthalten. Zugriff auf die Recordelemente erfolgt über qualifizierte Namen.

## Die Tabellensammlung im Speicher

Es gibt mehrere Möglichkeiten, Tabellenstrukturen im Speicher zu definieren. Diese Strukturen entsprechen Arrays in Programmiersprachen wie C oder Pascal.

### Index By

Die erste Variante ist eine Tabellenstruktur, die folgende Struktur hat.

### Nested Table
# Deklarationszwang

In PL/SQL gibt es einen Deklarationszwang. Jede Variable muss vor ihrer ersten Verwendung deklariert werden. Eine Deklaration besteht aus dem Namen der Variablen und dem Typ der Variablen. Optional ist eine Initialbelegung möglich. Eine FORWARD-Deklaration gibt es nicht.

## Die Veränderlichen – Variablen

Die Variablendeklaration hat folgenden Aufbau
In ihrem Gültigkeitsbereich darf jeder Variablenname nur einmal verwendet werden.

## Die Unveränderlichen – Konstanten

Die Konstantendeklaration hat folgenden Aufbau
In ihrem Gültigkeitsbereich darf jeder Konstantenname nur einmal verwendet werden. Konstanten können nur bei ihrer Deklaration einen Wert zugewiesen bekommen.

## Die Indizierten – PL/SQL-Tabellen

PL/SQL-Tabellendeklaration hat folgenden Aufbau
In ihrem Gültigkeitsbereich darf jede PL/SQL-Tabledeklaration nur einmal verwendet werden. Eine PL/SQL-Table Typdeklaration ist ein Objekt und beinhaltet neben den Daten eine Vielzahl von Methoden.

## Die Selektierten – Cursor

Ein Cursor ist eine Datenmenge, die durch ein SELECT-Statement erzeugt wird. Die Datenmenge kann eine leere Menge sein. Ein Cursor wird wie folgt deklariert.
Ausführliche Erläuterungen zum SELECT-Statement sind an hier zu finden.

## Die Fehlerhaften – Exception

Bei der Abarbeitung auftretende Fehler, damit sind keine ORACLE-Fehler (Fehler beim Zugriff auf die Datenbank) gemeint, sondern ausschließlich Fehler, die anwenderspezifisch sind, müssen deklariert werden, um diese abzufangen und zu behandeln. Eine Exceptiondeklaration wird wie folgt definiert.
Mit der PRAGMA-Deklaration kann der Exception eine negative, ganze Zahl, die kleiner oder gleich -20000 sein muss, zugewiesen werden.

## Gültigkeitsbereich und Sichtbarkeit

Der Gültigkeitsbereich gliedert sich in folgende Ebenen, begonnen mit der kleinsten.
* lokal innerhalb einer Prozedur/Funktion, definiert im Deklaraionsteile der Prozedur
* lokal innerhalb einer Prozedur/Funktion, definiert in der Parameterliste
* global innerhalb eines Packages, definiert im Deklarationsteil des Packages
* global innerhalb der Datenbanksession, definiert im Packageheader
Die Variable global_1 ist in der gesamten Session gültig und sichtbar. Zugegriffen wird auf diese Variable mit einem globalen Namen. Es ist möglich, mit dem Namen der Variablen zu zugrefen, wenn dieser im Header des eigenen Packages deklariert wurde. Aus Gründen der Übersichtlichkeit sollte aber auch in diesem Fall der globale Name verwendet werden. Die Variable global_2 ist nur im eigenen Package gültig und sichtbar. Die Parametervariable para_lokal_1 ist im Deklarationsteil und Ausführungsteil der Prozedur p1 gültig und sichtbar. Die lokale Variable lokal_1 der Prozedur p1 ist ab ihrer Deklaration bis zum Ende der Prozedur gültig und in der Prozedur p1 sichtbar. In der Funktion f1 ist diese Variable gültig, aber nicht sichtbar, da sie durch die lokale Variable lokal_1 der Funktion f1 in ihrer Sichtbarkeit überschrieben wird. Der Wert der lokalen Variablen lokal_1 der Prozedur p1 wird in der Funktion f1 aber nicht überschrieben, sonder bleibt erhalten. Die lokale Variable lokal_2 der Prozedur p1 ist in der Prozedur p1 und der Funktion f1 gültig und sichtbar. Die lokale Variable lokal_1 der Funktion f1 ist nur in dieser Funktion gültig und sichtbar.
Bei Auftreten einer Exception, unabhängig davon, ob von der Datenbank oder dem Anwenderprogramm ausgelöst, gehen alle lokalen Variablen verloren, aber alle globalen Variablen bleiben mit ihrem Inhalt erhalten. Dieser Aspekt ist zu berücksichtigen, wenn die Exception nach ihrer Behandlung eine Weiterarbeit ermöglicht. Sollen dabei die globalen Variablen neu initialisiert werden, muß das im Exceptionhandling ausprogrammiert werden.

# Anweisungen
## Ergibt sich aus – Ergibtanweisung

Die Ergibtanweisung wird zur Wertzuweisung an Variablen verwendet. Der grundlegende Aufgabe hat folgend Form.
Der Name der Variablen, der ein Wert zugewiesen wird kann eine einfache Variable oder Konstante, eine Struktur oder ein Strukturelement sein.
Der Operand besteht aus den Elementen
* Variablennamen,
* Funktionsausfrufen und
* Konstanten
die durch Operationszeichen verbunden und Klammerungen strukturiert werden. Die Elemente können unterschiedliche Datentypen haben; entweder erfolgt eine implizitr Typkonvertierung oder die Konvertierung wird durch Konvertierungsfunktionen vorgegeben.
Wenn ein Operand NULL ist, ist automatisch das Ergebnis NULL.

## Nichts tun – NULL-Anweisung

Eine besondere Ergibtanweisung ist die NULL-Anweisung.
Diese Anweisung wird benötigt, wenn eine Programmstruktur zwingend mindestens eine Programmzeile erfordert. Das ist besonders während der Entwicklungsphase von Programmen von Bedeutung, wenn die Programmstruktur schon vorgegeben ist, aber der eigentliche Programminhalt noch fehlt.

# Strukturierungen
## Grundlegener Aufbau

Für ein PL/SQL-Programm gibt es einen grundlegenden Aufbau

## Anonymer Block

Ein anonymer Block ist die kleinste Programmeinheit und wird häufig in Entwicklungsumgebungen verwendet um Programmteile zu testen.

## Die One-Way-Rückgebenden – Funktionen

Die Funktion als Struktur dient dazu, einen Wert als Returnwert zurückzugeben und hat folgende Struktur.

# Prozedur

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.

## Einstieg

Prozeduren sind nützlich, um regelmäßig wiederkehrende Arbeitsabläufe zu automatisieren z.B. um Installationsarbeiten durchzuführen.
Als Einstieg soll eine Prozedur dienen, die nur aus zwei Befehlen besteht.
Die Procedur wird im SQLPLUS aufgerufen mit dem Befehl:
Innerhalb eines PL/SQL-Scripts wird die Procedur nur durch Angabe ihres Namens aufgefufen.

## Parameterübergabe

Wenn man der Prozedur Parameter übergeben will, dann wird unterschieden in:
* IN: Die aufrufende Umgebung übergibt einen Wert an die Prozedur. Dieser Parameter kann innerhalb der Verarbeitung nicht verändert werden. IN ist der default Parameter-Modus
* OUT: Die aufrufende Umgebung übergibt eine Variable an die Prozedur, die innerhalb der Prozedur als nicht initialisiert betrachtet wird. Wenn innerhalb der Verarbeitung diesem Parameter ein Wert zugewiesen wird, dann wird dieser an die aufrufende Umgebung zurückgegeben.
* IN OUT: Die Aufrufende Umgebung übergibt eine Variable an die Prozedur. Diese kann innerhalb der Prozedur verwendet werden und auch geändert werden. Der geänderte Wert wird der aufrufenden Umgebung mitgeteilt.
Einfache Prozedur, die einen Parameter übergeben bekommt. Dieser Parameter wird durch den Befehl put_line wieder ausgegeben. Um die Ausgabe zu aktivieren, muss erst der SQL*Plus - Befehl 'set serveroutput on' ausgeführt werden.
Es ist auch möglich, Werte von Prozeduren verändern zu lassen:
Wird dieses zweite Beispiel verwendet, liefert der entsprechende Test:
wie zu erwarten, werden die Werte 13 und 55 ausgegeben.

# Bedingungen

Das Buch PL-SQL ist zurzeit in Überarbeitung! Änderungen auf dieser Seite bitte nur in Absprache mit mir.

## Allgemeines

Ein Cursor ist eine Art Zeilenvariable oder -zeiger, mit dem die Ergebnismenge einer SELECT-Anweisung zeilenweise (mit Hilfe der FETCH-Anweisung oder per CURSOR-FOR-LOOP) durchschritten wird.

## Cursor Schleifen
# Schleifen

Das Buch PL-SQL ist zurzeit in Überarbeitung! Änderungen an dieser Seite nur in Absprache mit mir.
Wie in jeder Sprache unterstützt auch PL/SQL Schleifen. Um richtig in die Programmierung einzusteigen, wollen wir hier zuallererst zwischen kopf- und fußgesteuerten Schleifen unterscheiden.
* Loop --- Until
* While
* For - Schleifen
Beispiele LOOP --- UNTIL:
(PL/SQL kennt keine REPEAT/UNTIL Konstruktion, stattdessen kann mit Hilfe der EXIT-Anweisung eine Schleife an beliebiger Stelle abgebrochen werden.)
Die Schleife wird solange ausgeführt, bis die Abbruchbedingung erfüllt ist. Die EXIT Bedingung kann an jeder beliebigen Stelle innerhalb der Schleife verwendet werden. Es ist zu beachten, daß bei unkorrekter Verwendung eine Endlosschleife ausgeführt wird. Wird die EXIT Bedingung am Beginn der Schleife verwendet, entspricht es einer WHILE Schleife.
Lesbarer ist allerdings die 'echte' WHILE Schleife:
Hier ein Beispiel für eine einfache FOR Schleife:
Die Schleife wird genau 10 mal ausgeführt.

# Cursor

Das Buch PL-SQL wird zurzeit überarbeitet. Änderungen an dieser Seite bitte nur in Absprache mit mir.

### Cursor sind Zeiger

Cursor ist englisch und bedeutet so viel wie "Zeiger". Im allgemeinen Gebrauch mit dem Computer hat das Wort vor allem zwei Bedeutungen: Einerseits bezeichnet man den Mauszeiger als Cursor und zum anderen den Strich, welcher die Eingabestelle bei Eingebeprogrammen (überall, wo man etwas schreiben kann) markiert.
Im Zusammenhang mit PL/SQL hat er noch eine dritte Bedeutung. Laut Wikipedia steht der Begriff hier eventuell als Abkürzung für Current Set of Records. Das bedeutet, er ist ein temporärer Bereich im Arbeitsspeicher, welcher Informationen über eine spezielle PL/SQL-Anweisung und ihre Ausgabe-Daten speichert und diese auch manipulieren kann. (Als Anweisung bezeichnet man einen Bereich zwischen zwei Semikola.) Wird ein Cursor in der Anweisung wieder geschlossen, gehen auch die in ihm enthaltenen Daten verloren.
In PL/SQL unterscheidet man, je nach Unterscheidungkriterium, insgesamt vier verschiedene Cursor: Das sind einerseits die statischen bzw. dynamischen und andererseits die expliziten bzw. impliziten Cursor. Die Anweisungen eines dynamischen Cursors werden erst zur Laufzeit festgelegt und können für jeden gültigen SQL-Anweisungstyp genutzt werden. Implementiert werden sie über EXECUTE IMMEDIATE-Anweisungen. Ein statischer Cursor hingegen wird bereits zur Kompilierzeit festgelegt und nur für DML-Anweisungen (also SELECT, INSERT, UPDATE, DELETE, MERGE oder SELECT FOR UPDATE) verwendet. Auftauchen können sie in zweierlei Formen: als explizit deklarierte oder implizit eingebettete Cursor.

### Implizierter Cursor

Implizite Cursor werden weder deklariert noch per Befehl geöffnet, bearbeitet oder geschlossen. Sie tauchen erst an der Stelle im Ausführungsteil auf, an der sie benötigt werden, und werden danach wieder geschlossen, wodurch die in ihnen enthaltenen Daten wieder gelöscht werden.
Hier ein Beispiel eines impliziten Cursors, mit dem ein einziger Datensatz gelesen werden kann:
Beispiel in einem anonymen Block:
Wenn man dabei ein SELECT-Statement angibt, das mehr als einen Satz als Ergebnis hat, wird eine Fehlermeldung ausgegeben, da nicht klar ist, welcher der gefundenen Datensätze in die Variable geschrieben werden soll.
Für SELECT-Statements, die mehr als einen Ergebnis-Satz liefern, kann die folgende Konstruktion verwendet werden:

### Expliziter Cursor

Explizite Cursor sind, wie der Name bereits erahnen lässt, im Deklarationsabschnitt deklariert. Dies kann ohne Parameter, mit Argumenten als Parameterliste oder auch mit einer RETURN-Klausel geschehen. Im Ausführungs- bzw. Exceptionabschnitt operiert man mit ihnen mithilfe der Befehle OPEN, FETCH und CLOSE zum Öffnen, Auslesen und Schließen. Dabei sind explizite Cursor die einzigen, die auch mehrzeilige Ausgaben machen können.
Hier ein Beispiel dazu in einem anonymen Block:

### Statusvariablen für Cursor

In einer Cursor-FOR-Schleife kann man die Anzahl der bereits gelesenen Sätze mit der Statusvariablen ROWCOUNT abfragen. Diese Variable ist jedoch nur im Inneren der Schleife gültig. Wenn man sie außerhalb der Schleife verwendet, dann wird ein Syntaxfehler ausgegeben.
Beispiel:
Das Programm hat folgende Ausgabe:

#### Rowcount bei einem Cursor ausgeben

Die auskommentierten Zeilen ergeben eine Fehlermeldung, wenn sie ausgeführt werden sollen.
Das Programm hat folgende Ausgabe:

# Exception-Handling

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.

## Vordefinierte Exceptions

Eine Auswahl an Exceptions. Eine vollständige Liste steht unter zur Verfügung.
| Name | Fehlercode | Beschreibung | Vorhanden ab |
| CURSOR_ALREADY_OPEN | ORA-06511 | Cursor ist bereits geöffnet | Oracle 7 |
| DUP_VAL_ON_INDEX | ORA-00001 | INSERT oder UPDATE eines Wertes, der bereits vorhanden ist, in einer als UNIQUE deklarierten Spalte | Oracle 7 |
| INVALID_CURSOR | ORA-01001 | Der Cursor ist nicht deklariert (existiert nicht) oder wurde nicht geöffnet | Oracle 7 |
| INVALID_NUMBER | ORA-01722 | Fehler bei impliziter Typkonvertierung, z.B. String enthält keinen numerischen Wert wird aber in NUMBER Spalte/Variable eingefügt bzw. übergeben | Oracle 7 |
| LOGIN_DENIED | ORA-01017 | Benutzername oder Passwort falsch | Oracle 7 |
| NO_DATA_FOUND | ORA-01403 | SELECT liefert kein Ergebnis: keine Daten wurden durch einen impliziten Cursor gefunden oder ein Index in einem Assoziativen Array existiert nicht | Oracle 7 |
| NOT_LOGGED_ON | ORA-01012 | Keine Verbindung zur Datenbank | Oracle 7 |
| PROGRAM_ERROR | ORA-06501 | Interner PL/SQL - Fehler | Oracle 7 |
| ROWTYPE_MISMATCH | ORA-06504 | Strukturvariablen inkompatibel | Oracle 7 |
| STORAGE_ERROR | ORA-06500 | Speicherprobleme | Oracle 7 |
| TIMEOUT_ON_RESOURCE | ORA-00051 | Datenbank-Sperre | Oracle 7 |
| TOO_MANY_ROWS | ORA-01422 | SELECT liefert mehr als eine Zeile | Oracle 7 |
| VALUE_ERROR | ORA-06502 | Fehler beim Arbeiten mit "Werten" in Variablen/Tabellen/Prozeduren, z.B. zu große Werte, Verletzung von Constraints, Fehler bei Typkonvertierungen (außer INVALID_NUMBER - Exception) | Oracle 7 |
| ZERO_DIVIDE | ORA-01476 | bei Division durch 0 | Oracle 7 |
| ACCESS_INTO_NULL | ORA-06530 | Zuweisung an ein nicht initialisiertes Objekt | Oracle 8 |
| ACCESS_INTO_NULL | ORA-06531 | Zugriff auf eine nicht initialisierte Collection (TABLE Variable oder VARRAY) | Oracle 8 |
| SELF_IS_NULL | ORA-030625 | Methode eines nicht initialisierten Objekts wird aufgerufen | Oracle 8 |
| SUBSCRIPT_BEYOND_COUNT | ORA-06533 | Index für Zugriff auf eine Collection (TABLE Variable oder VARRAY) ist nicht vorhanden | Oracle 8 |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | ungültiger Index bei Zugriff auf eine Collection (TABLE Variable oder VARRAY) | Oracle 8 |
| SYS_INVALID_ROWID | ORA-01410 | Zuweisung eines inkompatiblen/nicht konvertierbaren Datentyps zu einem ROWID-Element | Oracle 8 |
| CASE_NOT_FOUND | ORA-06592 | In einem CASE konnte kein WHEN ausgewählt werden und ELSE existiert nicht | Oracle 9i |
Exceptions gelten immer für den Block in dem sie deklariert sind. Da innerhalb eines Blocks auch mehrere Exceptions auftreten können, ist es möglich, diese hintereinander abzufragen. Mit "others" werden alle bis dahin unbehandelten Exceptions abgefangen.
Beispiel:
mit RAISE können Exceptions erzeugt werden oder auch aus dem aktuellen Block an den umschließenden Block weitergeleitet werden.
Es wird im inneren Block die Exception abgefangen, mit einer Meldung behandelt und danach an den äußeren Block weitergeleitet. Dort wird durch sqlcode und sqlerrm sowohl die Exception-Nummer als auch der Fehlertext der vordefinierten Exception ausgegeben.

## Referenzen

* ↑ http://download.oracle.com/docs/cd/E11882_01/server.112/e10880/toc.htm

# Variablen
## ORACLE Built-in Datentypen
### Text

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| CHAR(size) | Speicherung von Texten fester Länge | CHAR(8) | Codes oder Abkürzungen gleicher Länge | Maximale Größe 32767 Bytes. Default und Minimum sind 1 Byte. Beim Speichern wird der übergebene String mit Leerzeichen bis zur deklarierten Länge aufgefüllt. |
| NCHAR(size) | Speicherung von Texten fester Länge | NCHAR(8) | Codes oder Abkürzungen gleicher Länge | Ähnlich CHAR in Unicode, maximal 32767/2 bei AL16UTF16 encoding, und 32767/3 bei UTF8. |
| VARCHAR2(size) | Speicherung von Texten variabler Länge | VARCHAR2(200) | Zeichenketten bis maximal 32767 Byte | Häufig verwendeter Datentyp für Texte - Basisdatentyp. Bei der Deklaration muss eine Längenangabe erfolgen, dies ist die maximale Größe. Bei Vergleichsoperationen wird nur der tatsächlich gespeicherte String verglichen. |
| NVARCHAR2(size) | Speicherung von Texten variabler Länge | NVARCHAR2(200) | Zeichenketten bis maximal 32767 Byte | Ähnlich VARCHAR2 in Unicode, maximal 32767/2 bei AL16UTF16 encoding, und 32767/3 bei UTF8. |
| LONG | Speicherung von langen Texten | LONG | Texte bis zu 4 GB oder 2$^{31}$ -1 Bytes. | LONG sollte nicht mehr verwendet werden. Oracle empfiehlt statt dessen LOB zu verwenden, da LONG möglicherweise in Zukunft nicht mehr supported wird. |
| CLOB | Speicherung von langen Texten | CLOB | Texte bis zu (4 GiBytes - 1)*Blocksize (8, 16, 32, 64 oder 128 TiByte) | Character Large Object speichert lange Texte im Datenbankzeichensatz. |
| NCLOB | Speicherung von langen Texten | NCLOB | Texte bis zu (4 GiBytes - 1)*Blocksize (8, 16, 32, 64 oder 128 TiByte) | Character Large Object für Unicodezeichen. |

### Zahlen

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| NUMBER(p,s) | Speicherung von Zahlen mit fest definierter Genauigkeit(p) und Anzahl der Nachkommastellen(s) | NUMBER(22,2) | Währung | Sehr häufig verwendeter Datentyp für alle Zahlenformate - Basisdatentyp. 1 <= p <= 38, -84 <= s <= 127. Wertebereich 1.0 x 10$^{-130}$ bis 9.9...9 x 10$^{125}$. Integer können mit NUMBER(p) definiert werden, Fließkommazahlen mit NUMBER. |

### Datum

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| DATE | Speicherung von Datum und Zeit | DATE | Datum und Zeit (in Sekundengenauigkeit) | Erlaubtes Intervall von 1.1.4712 v.Chr. 31.12.9999 n.Chr.. |
| TIMESTAMP (fractional_seconds_precision) | Zeitstempel | TIMESTAMP(6) | z.B. Audit des Erstellungszeitpunkts eines Datensatzes | Datum mit Tag, Uhrzeit und den spezifizierten Sekundenbruchteilen (0-9) |
| TIMESTAMP (fractional_seconds_precision) WITH TIME ZONE | Zeitstempel | TIMESTAMP(6) | | wie TIMESTAMP mit Abweichung der Zeitzone |
| TIMESTAMP (fractional_seconds_precision) WITH LOCAL TIME ZONE | Zeitstempel | TIMESTAMP(6) | | wie vorhergehendes mit folgenden Ausnahmen: Beim Speichern werden die Daten auf die Zeitzone der Datenbank normalisiert, beim Auslesen auf die Zeitzone des Anwenders. |
| INTERVAL YEAR (year_precision) TO MONTH | Zeitintervall | INTERVAL YEAR (2) TO MONTH | | Zeitintervall in Jahren und Monaten, wobei year_precision die Zahl der Stellen im Jahresfeld des Datums ist (0-9). |
| INTERVAL DAY (day_precision) TO SECOND (fractional_seconds_precision) | Zeitintervall | INTERVAL DAY (2) TO SECOND (5) | | Zeitintervall in Tagen, Stunden, Minuten und Sekunden, wobei day_precision die Maximale Zahl der Ziffern bei den Tagen angibt (0-9). fractional_seconds_precision ist der Sekundenbruchteil (0-9). |

### Binärdaten

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| RAW (size) | Binärdaten | RAW(256) | | Binärdaten mit spezifizierter Länge, maximal 2000 Bytes. |
| LONG RAW | Binärdaten | LONG RAW | | Binärdaten mit variabler Länge. Maximale Größe 2 GB. Oracle empfiehlt statt LONG RAW besser BLOB zu verwenden, da die Verarbeitung weniger Restriktionen unterliegt. |
| BLOB | Binärdaten | BLOB | z.B. in der Datenbank gespeicherte Worddateien | Maximale Größe bis zu (4 GiBytes - 1)*Blocksize (8, 16, 32, 64 oder 128 TiByte) |
| BFILE | Verweis auf eine Binärdatei | BFILE | z.B. Verweis auf externe Videodateien | Verweis auf eine Binärdatei, die Außerhalb der Datenbank abgelegt ist. Maximale Größe 8 Terabyte |

### Sonstige

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| ROWID | Eindeutige Adresse einer Zeile in einer Tabelle | ROWID | z.B. temporäre Kennung eines Datensatzes ohne eindeutige ID | Nicht portable, interne Adresse für einen Datensatz; erhält man beim SELECT durch Angabe der Pseudospalte ROWID. |
| UROWID [(size)] | Logische Adresse einer Zeile in einer index-organized table. | UROWID | | Maximale Größe 4000 Bytes. |

## PL/SQL Datentypen

Neben den Built-in Datentypen, die auch für die Definition von Tabellen benutzt werden können, können in der Sprache PL/SQL weitere Datentypen verwendet werden.

### Zahlen

| Bezeichnung | Beschreibung | Deklarationsbeispiel | Anwendungsgebiet | Kommentar |
| PLS_INTEGER | Ganzzahlen mit einer Größe von -2.147.483.647 bis +2.147.483.647 | PLS_INTEGER[] | Normale Zahlen, Iterationen | Sehr häufig verwendeter Datentyp für Rechenoperationen (Rechnen mit Ganzzahlen), seit Version 10g identisch mit BINARY_INTEGER |
Hinzu kommen noch Datentypen, die der Benutzer selbst definieren kann. Hierzu gehören Objekte, die wie in der objektorientierten Programmierung eigene Methoden und Attribute haben, Arrays und Collections.

## Datentyp über Spalte festlegen

Variablenname Tabellenname.Spaltenname%type;
Definiert eine Variable des Typs der angegebenen Spalte.

## Datentyp über Tabelle festlegen

Variablenname Tabellenname%rowtype;
Definiert eine Variable des Typs der angegebenen Tabelle.
Beispiel :

## Benutzerdefinierte Datentypen

Benutzerdefinierte Datentypen werden mit Hilfe von "type datentyp is record(feld1 typ1 :=xyz, feld2 typ2 :=xyz, ..., feldn typn :=xyz);" definiert.
    declare  type t_adresse is record(  hausname adresse.hausname%type,  strasse adresse.strasse%type,  hausnummer adresse.hausnummer%type,  postleitzahl adresse.postleitzahl%type);  v_adresse t_adresse; begin  select hausname,strasse, hausnummer, postleitzahl into v_adresse from adresse where rownum = 1; end;
Das Beispielprogramm definiert einen eigenen Datentyp mit Namen t_adresse welcher die Felder hausname, strasse, hausnummer und postleitzahl enthält.
Mit diesem Datentyp wird eine Variable v_adresse definiert, welche mit einem Datensatz aus der Tabelle adresse gefüllt wird.
Mittels Punktnotation kann auf die Attribute zurückgegriffen werden "v_adresse.hausname := 'Nollenburgerweg 115';"

# DML-Befehle

Im Anweisungsteil eines PL/SQL-Programms können DML-Befehle ausgeführt werden.

### SELECT

Mit dem Select-Befehl werden Daten aus einer Tabelle oder View gelesen. Die Ergebnisse werden in PL/SQL-Variablen gespeichert. Dabei sind grundsätzlich zwei Fälle zu unterscheiden:
1. Es wird ein Select-Befehl verwendet, der entweder keinen oder maximal einen Satz als Ergebnis liefern kann.
2. Ein Select-Befehl kann auch mehrere Sätze als Ergebnis liefern.

#### Select-Befehl, der maximal einen Satz liefern kann

Select-Befehle, die maximal einen Datensatz lesen, sind meistens Zugriffe über den Primärschlüssel einer Tabelle. Dabei kann man entweder für jede Spalte des Ergebnissatzes eine einzelne Variable angeben oder eine Struktur angeben, in die die gelesenen Werte eingetragen werden.
Beispiel für die Verwendung einzelner Variablen:
Für jede Spalte, die durch das Select-Statement gelesen wird, muss eine Variable bereitgestellt werden.
Das Programm gibt folgendes Ergebnis aus:
Beispiel für die Verwendung einer Struktur:
Das Programm gibt folgendes Ergebnis aus:
Wenn kein Satz gefunden werden kann, dann wird eine Fehlermeldung ausgegeben.

#### Select-Befehl, der mehrere Sätze liefern kann

Wenn ein Select-Befehl verwendet wird, der auch mehr als einen einzigen Satz lesen kann, dann gibt es mehrere Möglichkeiten.
1. kann man mit einem Cursor arbeiten. Siehe Kapitel Cursor.
2. man kann auch alle Sätze in eine PL/SQL-Struktur einlesen
Beispiel für einen Bulk-Select

### INSERT, UPDATE, DELETE

Angenommen, es existiert eine Tabelle t_test mit folgender Definition:
CREATE TABLE t_test (i NUMBER);
Dann kann man die Daten, die in dieser Tabelle gespeichert werden, mit dem folgenden PL/SQL-Programm verändern:
Durch den Befehl COMMIT werden die Änderungen endgültig und die geänderten Sätze können auch von anderen Sessions gelesen oder weiter verändert werden.
Man hat auch die Möglichkeit, mit dem Befehl ROLLBACK die letzten Änderungen wieder zurückzunehmen. Das geht aber nur dann, wenn die Änderungen noch nicht mit COMMIT freigegeben wurden.

#### Vordefinierte Statusvariablen

Es kann sein, dass ein DML-Befehl keinen Satz findet der gelesen, geändert oder gelöscht werden kann. Um sich zu vergewissern, ob ein Satz gefunden wurde, gibt es die vordefinierte Variable sql%rowcount.
Das Programm ergibt folgende Ausgabe

# Schleifen

Das Buch PL-SQL ist zurzeit in Überarbeitung! Änderungen an dieser Seite nur in Absprache mit mir.
Wie in jeder Sprache unterstützt auch PL/SQL Schleifen. Um richtig in die Programmierung einzusteigen, wollen wir hier zuallererst zwischen kopf- und fußgesteuerten Schleifen unterscheiden.
* Loop --- Until
* While
* For - Schleifen
Beispiele LOOP --- UNTIL:
(PL/SQL kennt keine REPEAT/UNTIL Konstruktion, stattdessen kann mit Hilfe der EXIT-Anweisung eine Schleife an beliebiger Stelle abgebrochen werden.)
Die Schleife wird solange ausgeführt, bis die Abbruchbedingung erfüllt ist. Die EXIT Bedingung kann an jeder beliebigen Stelle innerhalb der Schleife verwendet werden. Es ist zu beachten, daß bei unkorrekter Verwendung eine Endlosschleife ausgeführt wird. Wird die EXIT Bedingung am Beginn der Schleife verwendet, entspricht es einer WHILE Schleife.
Lesbarer ist allerdings die 'echte' WHILE Schleife:
Hier ein Beispiel für eine einfache FOR Schleife:
Die Schleife wird genau 10 mal ausgeführt.

# Cursor

Das Buch PL-SQL wird zurzeit überarbeitet. Änderungen an dieser Seite bitte nur in Absprache mit mir.

### Cursor sind Zeiger

Cursor ist englisch und bedeutet so viel wie "Zeiger". Im allgemeinen Gebrauch mit dem Computer hat das Wort vor allem zwei Bedeutungen: Einerseits bezeichnet man den Mauszeiger als Cursor und zum anderen den Strich, welcher die Eingabestelle bei Eingebeprogrammen (überall, wo man etwas schreiben kann) markiert.
Im Zusammenhang mit PL/SQL hat er noch eine dritte Bedeutung. Laut Wikipedia steht der Begriff hier eventuell als Abkürzung für Current Set of Records. Das bedeutet, er ist ein temporärer Bereich im Arbeitsspeicher, welcher Informationen über eine spezielle PL/SQL-Anweisung und ihre Ausgabe-Daten speichert und diese auch manipulieren kann. (Als Anweisung bezeichnet man einen Bereich zwischen zwei Semikola.) Wird ein Cursor in der Anweisung wieder geschlossen, gehen auch die in ihm enthaltenen Daten verloren.
In PL/SQL unterscheidet man, je nach Unterscheidungkriterium, insgesamt vier verschiedene Cursor: Das sind einerseits die statischen bzw. dynamischen und andererseits die expliziten bzw. impliziten Cursor. Die Anweisungen eines dynamischen Cursors werden erst zur Laufzeit festgelegt und können für jeden gültigen SQL-Anweisungstyp genutzt werden. Implementiert werden sie über EXECUTE IMMEDIATE-Anweisungen. Ein statischer Cursor hingegen wird bereits zur Kompilierzeit festgelegt und nur für DML-Anweisungen (also SELECT, INSERT, UPDATE, DELETE, MERGE oder SELECT FOR UPDATE) verwendet. Auftauchen können sie in zweierlei Formen: als explizit deklarierte oder implizit eingebettete Cursor.

### Implizierter Cursor

Implizite Cursor werden weder deklariert noch per Befehl geöffnet, bearbeitet oder geschlossen. Sie tauchen erst an der Stelle im Ausführungsteil auf, an der sie benötigt werden, und werden danach wieder geschlossen, wodurch die in ihnen enthaltenen Daten wieder gelöscht werden.
Hier ein Beispiel eines impliziten Cursors, mit dem ein einziger Datensatz gelesen werden kann:
Beispiel in einem anonymen Block:
Wenn man dabei ein SELECT-Statement angibt, das mehr als einen Satz als Ergebnis hat, wird eine Fehlermeldung ausgegeben, da nicht klar ist, welcher der gefundenen Datensätze in die Variable geschrieben werden soll.
Für SELECT-Statements, die mehr als einen Ergebnis-Satz liefern, kann die folgende Konstruktion verwendet werden:

### Expliziter Cursor

Explizite Cursor sind, wie der Name bereits erahnen lässt, im Deklarationsabschnitt deklariert. Dies kann ohne Parameter, mit Argumenten als Parameterliste oder auch mit einer RETURN-Klausel geschehen. Im Ausführungs- bzw. Exceptionabschnitt operiert man mit ihnen mithilfe der Befehle OPEN, FETCH und CLOSE zum Öffnen, Auslesen und Schließen. Dabei sind explizite Cursor die einzigen, die auch mehrzeilige Ausgaben machen können.
Hier ein Beispiel dazu in einem anonymen Block:

### Statusvariablen für Cursor

In einer Cursor-FOR-Schleife kann man die Anzahl der bereits gelesenen Sätze mit der Statusvariablen ROWCOUNT abfragen. Diese Variable ist jedoch nur im Inneren der Schleife gültig. Wenn man sie außerhalb der Schleife verwendet, dann wird ein Syntaxfehler ausgegeben.
Beispiel:
Das Programm hat folgende Ausgabe:

#### Rowcount bei einem Cursor ausgeben

Die auskommentierten Zeilen ergeben eine Fehlermeldung, wenn sie ausgeführt werden sollen.
Das Programm hat folgende Ausgabe:

# Exception-Handling

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.

## Vordefinierte Exceptions

Eine Auswahl an Exceptions. Eine vollständige Liste steht unter zur Verfügung.
| Name | Fehlercode | Beschreibung | Vorhanden ab |
| CURSOR_ALREADY_OPEN | ORA-06511 | Cursor ist bereits geöffnet | Oracle 7 |
| DUP_VAL_ON_INDEX | ORA-00001 | INSERT oder UPDATE eines Wertes, der bereits vorhanden ist, in einer als UNIQUE deklarierten Spalte | Oracle 7 |
| INVALID_CURSOR | ORA-01001 | Der Cursor ist nicht deklariert (existiert nicht) oder wurde nicht geöffnet | Oracle 7 |
| INVALID_NUMBER | ORA-01722 | Fehler bei impliziter Typkonvertierung, z.B. String enthält keinen numerischen Wert wird aber in NUMBER Spalte/Variable eingefügt bzw. übergeben | Oracle 7 |
| LOGIN_DENIED | ORA-01017 | Benutzername oder Passwort falsch | Oracle 7 |
| NO_DATA_FOUND | ORA-01403 | SELECT liefert kein Ergebnis: keine Daten wurden durch einen impliziten Cursor gefunden oder ein Index in einem Assoziativen Array existiert nicht | Oracle 7 |
| NOT_LOGGED_ON | ORA-01012 | Keine Verbindung zur Datenbank | Oracle 7 |
| PROGRAM_ERROR | ORA-06501 | Interner PL/SQL - Fehler | Oracle 7 |
| ROWTYPE_MISMATCH | ORA-06504 | Strukturvariablen inkompatibel | Oracle 7 |
| STORAGE_ERROR | ORA-06500 | Speicherprobleme | Oracle 7 |
| TIMEOUT_ON_RESOURCE | ORA-00051 | Datenbank-Sperre | Oracle 7 |
| TOO_MANY_ROWS | ORA-01422 | SELECT liefert mehr als eine Zeile | Oracle 7 |
| VALUE_ERROR | ORA-06502 | Fehler beim Arbeiten mit "Werten" in Variablen/Tabellen/Prozeduren, z.B. zu große Werte, Verletzung von Constraints, Fehler bei Typkonvertierungen (außer INVALID_NUMBER - Exception) | Oracle 7 |
| ZERO_DIVIDE | ORA-01476 | bei Division durch 0 | Oracle 7 |
| ACCESS_INTO_NULL | ORA-06530 | Zuweisung an ein nicht initialisiertes Objekt | Oracle 8 |
| ACCESS_INTO_NULL | ORA-06531 | Zugriff auf eine nicht initialisierte Collection (TABLE Variable oder VARRAY) | Oracle 8 |
| SELF_IS_NULL | ORA-030625 | Methode eines nicht initialisierten Objekts wird aufgerufen | Oracle 8 |
| SUBSCRIPT_BEYOND_COUNT | ORA-06533 | Index für Zugriff auf eine Collection (TABLE Variable oder VARRAY) ist nicht vorhanden | Oracle 8 |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | ungültiger Index bei Zugriff auf eine Collection (TABLE Variable oder VARRAY) | Oracle 8 |
| SYS_INVALID_ROWID | ORA-01410 | Zuweisung eines inkompatiblen/nicht konvertierbaren Datentyps zu einem ROWID-Element | Oracle 8 |
| CASE_NOT_FOUND | ORA-06592 | In einem CASE konnte kein WHEN ausgewählt werden und ELSE existiert nicht | Oracle 9i |
Exceptions gelten immer für den Block in dem sie deklariert sind. Da innerhalb eines Blocks auch mehrere Exceptions auftreten können, ist es möglich, diese hintereinander abzufragen. Mit "others" werden alle bis dahin unbehandelten Exceptions abgefangen.
Beispiel:
mit RAISE können Exceptions erzeugt werden oder auch aus dem aktuellen Block an den umschließenden Block weitergeleitet werden.
Es wird im inneren Block die Exception abgefangen, mit einer Meldung behandelt und danach an den äußeren Block weitergeleitet. Dort wird durch sqlcode und sqlerrm sowohl die Exception-Nummer als auch der Fehlertext der vordefinierten Exception ausgegeben.

## Referenzen

* ↑ http://download.oracle.com/docs/cd/E11882_01/server.112/e10880/toc.htm

# Prozedur

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.

## Einstieg

Prozeduren sind nützlich, um regelmäßig wiederkehrende Arbeitsabläufe zu automatisieren z.B. um Installationsarbeiten durchzuführen.
Als Einstieg soll eine Prozedur dienen, die nur aus zwei Befehlen besteht.
Die Procedur wird im SQLPLUS aufgerufen mit dem Befehl:
Innerhalb eines PL/SQL-Scripts wird die Procedur nur durch Angabe ihres Namens aufgefufen.

## Parameterübergabe

Wenn man der Prozedur Parameter übergeben will, dann wird unterschieden in:
* IN: Die aufrufende Umgebung übergibt einen Wert an die Prozedur. Dieser Parameter kann innerhalb der Verarbeitung nicht verändert werden. IN ist der default Parameter-Modus
* OUT: Die aufrufende Umgebung übergibt eine Variable an die Prozedur, die innerhalb der Prozedur als nicht initialisiert betrachtet wird. Wenn innerhalb der Verarbeitung diesem Parameter ein Wert zugewiesen wird, dann wird dieser an die aufrufende Umgebung zurückgegeben.
* IN OUT: Die Aufrufende Umgebung übergibt eine Variable an die Prozedur. Diese kann innerhalb der Prozedur verwendet werden und auch geändert werden. Der geänderte Wert wird der aufrufenden Umgebung mitgeteilt.
Einfache Prozedur, die einen Parameter übergeben bekommt. Dieser Parameter wird durch den Befehl put_line wieder ausgegeben. Um die Ausgabe zu aktivieren, muss erst der SQL*Plus - Befehl 'set serveroutput on' ausgeführt werden.
Es ist auch möglich, Werte von Prozeduren verändern zu lassen:
Wird dieses zweite Beispiel verwendet, liefert der entsprechende Test:
wie zu erwarten, werden die Werte 13 und 55 ausgegeben.

# Funktion

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.
Neben den vielen Funktionen, die die SQL-Sprache schon bietet, kann man eigene Funktionen definieren. Funktionen haben immer einen oder mehrere Input-Parameter und genau einen Ergebniswert.
Hier ein ganz einfaches Beispiel einer Funktion, die einen String als Input erwartet und einen String als Ergebnis liefert. Die Verarbeitung der Funktion besteht darin, den Input-Parameter um ein 'x' zu erweitern.
Diese Funktion kann man nun genauso verwenden wie die anderen bereits vordefinierten Funktionen. Man muss nur darauf achten, dass man die richtige Anzahl an Parametern angibt und die passenden Datentypen wählt. Beispielaufruf:
Ergebnis:
In dem Anweisungsteil der Funktion können beliebig komplexe PL/SQL-Anweisungen angegeben werden. Ein Beispiel für eine etwas komplexere Funktion:
Funktionen kann man gut testen, indem man sie in einem SELECT einsetzt, der aus der Tabelle dual liest. Diese Tabelle enthält genau einen Satz mit einer Spalte. Eigentlich ist man aber an diesem Satz gar nicht interessiert, sondern man will durch diesen SELECT nur bewirken, dass die Funktion genau einmal aufgerufen wird. Aufrufbeispiel:
Ergebnis:
Hinweise:
* Die 1. Funktion ist deterministisch d.h. wenn man die Funktion zwei mal mit dem selben Eingabe-Parameter aufruft, dann liefert sie immer den selben Output.
* Die 2. Funktion ist nicht-deterministisch d.h. ihr Ergebnis ist auch von anderen Informationen abhängig, als nur den übergebenen Parametern. Wenn jemand die Sätze in der Tabelle ben01.templ ändert, dann kann die Funktion anzma bei gleichem Eingabe-Parameter ein anderes Ergebnis liefern.

# Einführung1

Mit der Oracle Funktion DBMS_OUTPUT.PUT_LINE können Zeichenketten ausgegeben werden, die nicht das Ergebnis einer SQL-Abfrage sind. Allerdings dürfen die Zeichenketten nicht länger als 255 Zeichen sein, sonst kommt es zu einem Abbruch. Wir werden noch eine Funktion vorstellen, die auch längere Zeichenketten ausgeben kann, aber vorerst müssen wir mit 255 Zeichen vorlieb nehmen. In der Oracle 10g Version sollte die Funktion auch mehr Zeichen ausgeben können. Als Einstieg wollen wir nun in SQL*PLUS unsere erste Ausgabe erhalten.
Vorher nicht vergessen in SQL*PLUS auf
zu stellen. Das ist einer der häufigsten Dinge, die vergessen werden und einen beim Testen zur Verzweiflung bringen.
In PL*SQL würde unser Beispiel 'Hello World' ungefähr so aussehen

#### Listing: HelloWorld.SQL

Das war doch gar nicht so schwer, oder?

#### Vorgehensweise in SQL*PLUS

Es empfiehlt sich die Anlage einer Datei z.B. mit dem Namen helloworld.plsql:
Ein Aufruf von sqlplus nach dem Schema:
kompiliert die Prozedur. Eventuelle Fehlermeldungen können in SQL*PLUS mit
eingesehen werden.
Der Aufruf der Prozedur kann dann mit
erfolgen.

# Literatur
## andere Wikibooks zu verwandten Themen

* Einführung in SQL
* Oracle

## Infos in Wikipedia

* w:PL/SQL
* w:Oracle (Datenbanksystem)
* w:Transact SQL

## Links zum WWW zu Oracle PL/SQL

* Oracle PL/SQL Users Guide
* Tutorial für PL/SQL
* Umfangreiches PL/SQL Tutorial
* Oracle FAQ’s: PL/SQL
* Ask Tom
* Performanceoptimierung von PL/SQL-Routinen: native Kompilierung
* Kostenfreie PL/SQL Tutorials

## Links zum WWW zu Microsoft TSQL

* Transact-SQL Referenz von Microsoft
* Transact-SQL Referenz von Sybase
* Transact-SQL Tutorial

# Grundlegender Aufbau
## Grundlegener Aufbau

Für ein PL/SQL-Programm gibt es einen grundlegenden Aufbau

# Anonyme Blöcke1
## Anonyme Blöcke

Die anonymen Blöcke sind die kleinste Programmeinheit, die es in PL/SQL gibt.

# Funktion

Das Buch PL-SQL wird zurzeit überarbeitet! Änderungen an dieser Seite bitte nur in Absprache mit mir.
Neben den vielen Funktionen, die die SQL-Sprache schon bietet, kann man eigene Funktionen definieren. Funktionen haben immer einen oder mehrere Input-Parameter und genau einen Ergebniswert.
Hier ein ganz einfaches Beispiel einer Funktion, die einen String als Input erwartet und einen String als Ergebnis liefert. Die Verarbeitung der Funktion besteht darin, den Input-Parameter um ein 'x' zu erweitern.
Diese Funktion kann man nun genauso verwenden wie die anderen bereits vordefinierten Funktionen. Man muss nur darauf achten, dass man die richtige Anzahl an Parametern angibt und die passenden Datentypen wählt. Beispielaufruf:
Ergebnis:
In dem Anweisungsteil der Funktion können beliebig komplexe PL/SQL-Anweisungen angegeben werden. Ein Beispiel für eine etwas komplexere Funktion:
Funktionen kann man gut testen, indem man sie in einem SELECT einsetzt, der aus der Tabelle dual liest. Diese Tabelle enthält genau einen Satz mit einer Spalte. Eigentlich ist man aber an diesem Satz gar nicht interessiert, sondern man will durch diesen SELECT nur bewirken, dass die Funktion genau einmal aufgerufen wird. Aufrufbeispiel:
Ergebnis:
Hinweise:
* Die 1. Funktion ist deterministisch d.h. wenn man die Funktion zwei mal mit dem selben Eingabe-Parameter aufruft, dann liefert sie immer den selben Output.
* Die 2. Funktion ist nicht-deterministisch d.h. ihr Ergebnis ist auch von anderen Informationen abhängig, als nur den übergebenen Parametern. Wenn jemand die Sätze in der Tabelle ben01.templ ändert, dann kann die Funktion anzma bei gleichem Eingabe-Parameter ein anderes Ergebnis liefern.
* Druckversion des Buches Name des Buches
* Dieses Buch umfasst derzeit etwa ? DIN-A4-Seiten einschließlich Bilder.
* Wenn Sie dieses Buch drucken oder die Druckvorschau Ihres Browsers verwenden, ist diese Notiz nicht sichtbar.
* Zum Drucken klicken Sie in der linken Menüleiste im Abschnitt „Drucken/exportieren“ auf Als PDF herunterladen.
* Mehr Informationen über Druckversionen siehe Hilfe:Fertigstellen/ PDF-Versionen.
* Hinweise:
* Für einen reinen Text-Ausdruck kann man die Bilder-Darstellung im Browser deaktivieren:
* Internet-Explorer: Extras > Internetoptionen > Erweitert > Bilder anzeigen (Häkchen entfernen und mit OK bestätigen)
* Mozilla Firefox: Extras > Einstellungen > Inhalt > Grafiken laden (Häkchen entfernen und mit OK bestätigen)
* Opera: Ansicht > Bilder > Keine Bilder
* Texte, die in Klappboxen stehen, werden nicht immer ausgedruckt (abhängig von der Definition). Auf jeden Fall müssen sie ausgeklappt sein, wenn sie gedruckt werden sollen.
* Die Funktion „Als PDF herunterladen“ kann zu Darstellungsfehlern führen.