vorheriges KapitelInhaltsverzeichnisIndexInfoseitenächstes Kapitel



18


PL/SQL: Eine Einführung

Ziele

Einführung

Datentypen in PL/SQL

Die Struktur eines PL/SQL-Blocks

Der DECLARE-Abschnitt

Der PROCEDURE-Abschnitt

Der EXCEPTION-Abschnitt

Alles zusammen

Gespeicherte Prozeduren, Pakete und Trigger

Zusammenfassung

Fragen & Antworten

Workshop



Ziele

Mit PL/SQL hat Oracle eine Technologie geschaffen, die den Einsatz von SQL in der Art einer prozeduralen Sprache erlaubt. Am Ende dieses Tages sollten Sie ...



Einführung

In den bisherigen Lektionen haben wir uns fast ausschließlich mit Standard-SQL beschäftigt. Eine Einführung zu PL/SQL setzt die Kenntnis von Standard-SQL voraus. Die Sprache SQL dient der Kommunikation mit einer relationalen Datenbank. Man kann damit Datenbanken abfragen und Tabellen in der Datenbank modifizieren. Mit SQL-Anweisungen weist man die Datenbank an, was zu tun ist, und nicht, wie es zu tun ist. Der Abfrageoptimierer legt den Weg für die effizienteste Ausführung der Anweisung fest. Schickt man in Standard-SQL eine Folge von SQL-Anweisungen an den Server, führt der Server die Anweisungen einzeln in chronologischer Reihenfolge aus.


PL/SQL ist die prozedurale Sprache von Oracle. Sie umfaßt die Standardsprache von SQL und einen weiten Bereich von Befehlen, mit denen man die Ausführung von SQL-Anweisungen entsprechend unterschiedlicher Bedingungen steuern kann. PL/SQL kann auch Laufzeitfehler behandeln. Möglichkeiten wie Schleifen und IF...THEN-Anweisungen verleihen PL/SQL die Leistungsfähigkeit von Programmiersprachen der dritten Generation. Es lassen sich interaktive, benutzerfreundliche Programme schreiben, die Werte an Variablen übergeben können. Zum Lieferumfang gehören verschiedene vordefinierte Pakete, zum Beispiel für die Anzeige von Meldungen für den Benutzer.


Tag 18 behandelt die folgenden Schlüsselmerkmale von PL/SQL:



Datentypen in PL/SQL

Die meisten Datentypen sind weitgehend einheitlich definiert, wobei aber bei den einzelnen Implementierungen gewisse Eigenheiten hinsichtlich der Speicherung und der internen Verarbeitung zu beachten sind. Variablen, die man in PL/SQL-Blöcken deklariert, müssen gültige Datentypen aufweisen. Die folgenden Unterabschnitte beschreiben kurz die in PL/SQL verfügbaren Datentypen.


Oracle stellt in PL/SQL sogenannte Untertypen zu den Datentypen bereit. Beispielsweise hat der Datentyp NUMBER einen Untertyp INTEGER. Mit Untertypen läßt sich die Kompatibilität der Datentypen eines PL/SQL-Programms zu Datentypen in anderen Programmen wie zum Beispiel Cobol erreichen, insbesondere wenn man PL/SQL-Code in ein anderes Programm einbettet. Untertypen sind lediglich alternative Namen für die Datentypen von Oracle, und man muß demnach die Regeln des zugehörigen Originaltyps beachten.


Wie in den meisten Implementierungen von SQL wird die Groß-/Kleinschreibung in der Syntax einer Anweisung nicht berücksichtigt. PL/SQL erlaubt in den Befehlen sowohl Groß- als auch Kleinbuchstaben.


Zeichenstrings

Die in PL/SQL als Zeichenstrings vorhandenen Datentypen sind allgemein für die Aufnahme von alphanumerischen Werten definiert. Beispiele für Zeichenstring-Datentypen sind Namen, Codes, Beschreibungen und Seriennummern, die Zeichen enthalten.


In Variablen vom Datentyp CHAR lassen sich Zeichenstrings fester Länge mit maximal 32767 Byte speichern, obwohl man sich in einer Tabelle kaum einen derartig großen Wert dieses Datentyps vorstellen kann.


Untertyp: CHARACTER


VARCHAR2 speichert Zeichenstrings variabler Länge. Normalerweise verwendet man VARCHAR2 anstelle von CHAR, um Daten veränderlicher Länge zu speichern, beispielsweise Personennamen. Die maximale Länge von VARCHAR2 beträgt ebenfalls 32767 Byte.


Untertypen: VARCHAR, STRING


LONG speichert ebenfalls Strings variabler Länge, wobei die maximale Zeichenzahl 32760 Byte beträgt. In der Regel verwendet man LONG, um längere Texte (etwa Anmerkungen) zu speichern, obwohl sich VARCHAR2 genausogut dafür eignet.



Numerische Datentypen

In einer Oracle-Datenbank lassen sich im Datentyp NUMBER beliebige Zahlenwerte speichern.


Die Genauigkeit der Daten läßt sich im Typ NUMBER mit der folgenden Syntax festlegen:


NUMBER (Genauigkeit, Skala)


Untertypen: DEC, DECIMAL, DOUBLE PRECISION, INTEGER, INT, NUMERIC, REAL, SMALLINT, FLOAT


PLS_INTEGER definiert Spalten, die ganze Zahlen mit Vorzeichen (negative Zahlen) enthalten können.



Binäre Datentypen

Binäre Datentypen speichern Daten, die in einem binären Format vorliegen, beispielsweise Grafiken oder Fotos. Zu diesen Datentypen gehören RAW und LONG RAW.



Der Datentyp DATE

DATE ist der gültige Oracle-Datentyp zur Speicherung von Datumswerten. Wenn man eine Spalte als DATE definiert, gibt man keine Länge an, da die Länge des DATE-Felds implizit enthalten ist. Das Format eines Oracle-Datums lautet zum Beispiel 01.10.97 oder 01-OCT-97.



BOOLEAN

BOOLEAN speichert die Werte TRUE, FALSE und NULL. Wie DATE erfordert BOOLEAN keine Parameter, wenn man diesen Datentyp für die Definition einer Spalte oder einer Variablen angibt.



ROWID

ROWID ist eine Pseudospalte, die in jeder Tabelle einer Oracle-Datenbank vorhanden ist. ROWID wird im binären Format gespeichert und identifiziert die Zeilen einer Tabelle. Indizes verwenden ROWIDs als Zeiger auf Daten.



Die Struktur eines PL/SQL-Blocks

PL/SQL ist eine Sprache mit Blockstruktur, das heißt PL/SQL-Programme sind in logische Codeblöcke unterteilt. Innerhalb eines PL/SQL-Codeblocks lassen sich Prozesse wie Datenmanipulationen oder Abfragen formulieren. Ein PL/SQL-Block baut sich aus den folgenden Teilen auf:


Ein Block ist eine logische Einheit des PL/SQL-Codes, der zumindest einen PROCEDURE-Abschnitt und optional die Abschnitte DECLARE und EXCEPTION enthält.

Die grundlegende Struktur eines PL/SQL-Blocks stellt sich wie folgt dar:


Beachten Sie, daß es nur zwei obligatorische Elemente in einem PL/SQL-Block gibt: das zweite BEGIN und das erste END, die den PROCEDURE-Abschnitt kennzeichnen. Natürlich wird man dazwischen noch Anweisungen schreiben. Wenn man das erste BEGIN angibt, muß man auch das zweite END schreiben, und umgekehrt.



Kommentare

Was wäre ein Programm ohne Kommentare? Alle Programmiersprachen bieten Befehle, mit denen man Kommentare in den Code einfügen kann. PL/SQL bildet auch hier keine Ausnahme. Die Kommentare auf den Zeilen in der oben dargestellten Blockstruktur beschreiben jeden Befehl. In PL/SQL kennzeichnet man Kommentare wie folgt:


PL/SQL unterstützt direkt die Befehle der Datenmanipulationssprache (DML) und Datenbankabfragen. Dagegen werden die Befehl der Datendefinitionssprache (DLL) nicht unterstützt. Im allgemeinen setzt man PL/SQL ein, um die Daten innerhalb der Datenbankstruktur zu manipulieren, aber nicht, um diese Strukturen zu verändern.


Der DECLARE-Abschnitt

Der DECLARE-Abschnitt in einem PL/SQL-Codeblock besteht aus Variablen, Konstanten, Cursordefinitionen und speziellen Datentypen. Als PL/SQL-Programmierer können Sie alle Variablentypen innerhalb Ihrer Codeblöcke deklarieren. Allerdings müssen Sie jeder definierten Variablen einen Datentyp zuweisen, der den Regeln von Oracle für den betreffenden Datentyp entspricht. Variablen müssen außerdem den Standards von Oracle zur Benennung genügen.



Variablenzuweisung

Variablen sind Werte, die sich innerhalb eines PL/SQL-Blocks verändern lassen. PL/SQL-Variablen ist ein gültiger Datentyp bei der Deklaration zuzuweisen. Bei Bedarf kann man Variablen initialisieren. Das folgende Beispiel definiert einen Satz von Variablen im DECLARE-Abschnitt eines Blocks:


DECLARE
owner char(10);
tablename char(30);
bytes number(10);
today date;


Der DECLARE-Abschnitt eines Blocks ist nicht selbständig ausführbar. Der Abschnitt wird mit der Anweisung DECLARE eingeleitet. Daran schließen sich die Definitionen der Variablen auf jeweils eigenen Zeilen an. Jede Variablendeklaration endet mit einem Semikolon.

Im DECLARE-Abschnitt kann man Variablen auch initialisieren. Dazu ein Beispiel:


DECLARE
Kunde char(30);
Rechnungsjahr number(2) := '97';


Mit dem Symbol := initialisiert man eine Variable im DECLARE-Abschnitt, das heißt man weist dieser Variablen einen Anfangswert zu. Eine als NOT NULL definierte Variable muß initialisiert werden.


DECLARE
Kunde char(30);
Rechnungsjahr number(2) NOT NULL := '97';


Die Klausel NOT NULL in der Definition von Rechnungsjahr ähnelt einer Spaltendefinition in einer CREATE TABLE-Anweisung.


Konstantenzuweisung

Konstanten definiert man in der gleichen Weise wie Variablen. Konstante Werte sind allerdings statisch und ändern sich nicht. Im obigen Beispiel stellt Rechnungsjahr wahrscheinlich eine Konstante dar.


Jede Variablendeklaration muß mit einem Semikolon enden.


Cursordefinitionen

Ein Cursor ist ein weiterer Variablentyp in PL/SQL. Bei einer Variablen denkt man gewöhnlich an einen einzelnen Wert. Ein Cursor ist eine Variable, die auf eine Datenzeile in der Ergebnismenge einer Abfrage zeigt. In einer mehrzeiligen Ergebnismenge braucht man eine Möglichkeit, um durch jeden Datensatz zu scrollen und die Daten zu analysieren. Genau dazu dient ein Cursor. Wenn der PL/SQL-Block die Ergebnismenge einer Abfrage innerhalb des Blocks bearbeitet, zeigt ein Cursor auf die zurückgegebene Zeile. Das folgende Beispiel zeigt, wie man in PL/SQL einen Cursor definiert:


DECLARE
cursor employee_cursor is
select * from employees;


Ein Cursor ist einer Sicht ähnlich. Mit einer Schleife im PROCEDURE-Abschnitt kann man durch einen Cursor scrollen. Diese Technik wird in Kürze gezeigt.



Das Attribut %TYPE

Das Attribut %TYPE liefert den Datentyp einer Variablen oder einer Datenbankspalte. Statt den Datentyp fest im PL/SQL-Block zu kodieren, läßt sich mit %TYPE die Konsistenz der Datentypen in den Codeblöcken gewährleisten.


DECLARE
cursor employee_cursor is
select emp_id, emp_name from employees;
id_num employees.emp_id%TYPE;
name employees.emp_name%TYPE;


Die Variable id_num wird vom selben Datentyp wie emp_id in der Tabelle EMPLOYEES deklariert. Mit %TYPE übernimmt man bei der Deklaration der Variablen name den Datentyp der Spalte emp_name in der Tabelle EMPLOYEES.


Das Attribut %ROWTYPE

Variablen sind nicht auf einzelne Werte beschränkt. Eine Variable kann zum Beispiel mit einem definierten Cursor verbunden sein. Das Attribut %ROWTYPE liefert einen Datensatztyp zurück, der eine ganze Zeile in einer Tabelle (oder Sicht) repräsentiert. Damit kann man den Datentyp der Variablen auf die Datentypen der Spalten in der betreffenden Datenzeile des Cursors festlegen. Im folgenden Beispiel erzeugt das Attribut %ROWTYPE eine Datensatzvariable.


DECLARE
cursor employee_cursor is
select emp_id, emp_name from employee;
employee_record employee_cursor%ROWTYPE;


Dieses Beispiel deklariert eine Variable namens employee_record. Das Attribut %ROWTYPE definiert diese Variable vom selben Datentyp wie die gesamte Datenzeile im employee_cursor. Variablen, die mit dem Attribut %ROWTYPE deklariert sind, bezeichnet man auch als Aggregatvariable.


Das Attribut %ROWCOUNT

Das PL/SQL-Attribut %ROWCOUNT liefert die Anzahl der Zeilen, die von SQL-Anweisungen im betreffenden Block aus einem Cursor zurückgegeben wurden.


DECLARE
cursor employee_cursor is
select emp_id, emp_name from employees;
records_processed := employee_cursor%ROWCOUNT;


In diesem Beispiel stellt die Variable records_processed die aktuelle Anzahl der Zeilen dar, auf die der PL/SQL-Block in employee_cursor zugegriffen hat.

Achten Sie bei der Deklaration von Variablen auf Konflikte mit Tabellennamen. Deklariert man zum Beispiel eine Variable mit demselben Namen wie eine Tabelle, auf die man im PL/SQL-Code zugreifen möchte, hat die lokale Variable den Vorrang gegenüber dem Tabellennamen.


Der PROCEDURE-Abschnitt

Der PROCEDURE-Abschnitt ist der einzige obligatorische Teil eines PL/SQL-Blocks. Dieser Teil des Blocks ruft Variablen auf und manipuliert mit Cursor die Daten in der Datenbank. Der PROCEDURE-Abschnitt ist der Hauptteil eines Blocks und enthält Bedingungsanweisungen und SQL-Befehle.



BEGIN...END

In einem Block kennzeichnet die Anweisung BEGIN den Anfang einer Prozedur. Analog dazu markiert die END-Anweisung das Ende der Prozedur. Das folgende Beispiel zeigt die Grundstruktur des PROCEDURE-Abschnitts:



Befehle zur Cursor-Steuerung

Nachdem Sie gelernt haben, wie man Cursor in einem PL/SQL-Block definiert, müssen Sie wissen, wie man auf die definierten Cursor zugreift. Dieser Abschnitt erläutert die grundlegenden Befehle zur Cursor-Steuerung: DECLARE, OPEN, FETCH und CLOSE.



DECLARE

Weiter vorn in der heutigen Lektion wurde gezeigt, wie man einen Cursor im DECLARE-Abschnitt eines Blocks definiert. Die DECLARE-Anweisung gehört zur Liste der Cursor-Steuerbefehle.



OPEN

Genau wie man ein Buch nicht lesen kann, bevor man es öffnet, muß man einen definierten Cursor erst öffnen und kann erst dann darauf zugreifen. Einen Cursor öffnet man mit dem Befehl OPEN, wie es das folgende Beispiel zeigt:



FETCH

Der Befehl FETCH füllt eine Variable mit den Werten aus einem Cursor. Hier zwei Beispiele für den Einsatz von FETCH: das erste füllt eine Aggregatvariable, das andere Beispiel zwei einzelne Variablen.


DECLARE
cursor employee_cursor is
select emp_id, emp_name from employees;
employee_record employee_cursor%ROWTYPE;
BEGIN
open employee_cursor;
loop
fetch employee_cursor into employee_record;
end loop;
close employee_cursor;
END


Das obige Beispiel holt die aktuelle Zeile des Cursors in die Aggregatvariable employee_record. Der Cursor wird in einer Schleife durchlaufen. Ansonsten führt dieses Beispiel keine sinnvollen Aktionen aus.

DECLARE
cursor employee_cursor is
select emp_id, emp_name from employees;
id_num employees.emp_id%TYPE;
name employees.emp_name%TYPE;
BEGIN
open employee_cursor;
loop
fetch employee_cursor into id_num, name;
end loop;
close employee_cursor;
END


Dieses Beispiel holt die aktuelle Zeile des Cursors in die Variablen id_num und name, die im DECLARE-Abschnitt definiert wurden.


CLOSE

Wenn man die Arbeit mit einem Cursor in einem Block beendet hat, sollte man den Cursor schließen. Der entsprechende Befehl lautet CLOSE.


Nachdem ein Cursor geschlossen wurde, existiert die Ergebnismenge einer Abfrage nicht mehr. Man muß den Cursor erneut öffnen, um auf die zugehörige Datenmenge zuzugreifen.


Bedingungsanweisungen

Nun kommen wir zur eigentlichen Würze von PL/SQL. Mit den Bedingungsanweisungen können Sie die Verarbeitung der SQL-Anweisungen beeinflussen. Die PL/SQL-Bedingungsanweisungen findet man so oder in ähnlicher Form in den meisten Sprachen der dritten Generation wieder.



IF...THEN

Die Bedingungsanweisung IF...THEN dürfte den meisten Programmierern am vertrautesten sein. Die IF...THEN-Anweisung schreibt die Ausführung bestimmter Aktionen vor, wenn die angegebenen Bedingungen erfüllt sind. Die Struktur einer IF...THEN-Anweisung sieht folgendermaßen aus:


Prüft man auf zwei Bedingungen, kann man die Anweisung wie folgt schreiben:


Bei mehr als zwei Bedingungen läßt sich die Anweisung folgendermaßen formulieren:


Die Struktur des letzten Beispiels ist folgendermaßen zu interpretieren: Wenn Bedingung1 erfüllt ist, dann führe Anweisung1 aus. Wenn Bedingung2 erfüllt ist, dann führe Anweisung2, andernfalls Anweisung3 aus. IF...THEN-Anweisungen lassen sich auch in anderen Anweisungen und/oder Schleifen verschachteln.


Schleifen (LOOP)

In einem PL/SQL-Block kann man Anweisung in Schleifen solange wiederholen, bis die angegebene Bedingung erfüllt ist. Man unterscheidet drei Arten von Schleifen.


Als einfachste Form der Schleifenanweisungen realisiert LOOP eine Endlosschleife, die man häufig für das Durchlaufen eines Cursors einsetzt. Damit eine derartige Schleife terminiert, muß man einen Austrittspunkt spezifizieren. Zum Beispiel soll beim Durchlaufen eines Cursors die Schleife nach der Verarbeitung der letzten Zeile im Cursor verlassen werden:


BEGIN
open employee_cursor;
LOOP
FETCH employee_cursor into employee_record;
EXIT WHEN employee_cursor%NOTFOUND;
statement1;
.
.
.
END LOOP;
close employee_cursor;
END;


Das Cursor-Attribut %NOTFOUND liefert das Ergebnis TRUE, wenn die letzte FETCH-Operation keine Zeile aus dem Cursor zurückgegeben hat. Im Beispiel wird damit die Schleife verlassen, wenn der Cursor keine Daten mehr enthält. Gibt man diese Anweisung nicht in der Schleife an, läuft die Schleife auf immer und ewig.


Eine WHILE-Schleife führt Befehle aus, solange eine bestimmte Bedingung TRUE ist. Sobald die Bedingung nicht mehr TRUE ist, gibt die Schleife die Steuerung des Programmablaufs an die nächste Anweisung nach der Schleife ab.


DECLARE
cursor payment_cursor is
select cust_id, payment, total_due from payment_table;
cust_id payment_table.cust_id%TYPE;
payment payment_table.payment%TYPE;
total_due payment_table.total_due%TYPE;
BEGIN
open payment_cursor;
WHILE payment < total_due LOOP
FETCH payment_cursor into cust_id, payment, total_due;
EXIT WHEN payment_cursor%NOTFOUND;
insert into underpay_table
values (cust_id, 'STILL OWES');
END LOOP;
close payment_cursor;
END;


Das obige Beispiel verwendet die WHILE-Schleife, um den Cursor zu durchlaufen und die Befehle innerhalb der Schleife auszuführen, solange die Bedingung payment < total_due erfüllt ist.

Im vorherigen Block läßt sich auch die FOR-Schleife einsetzen, um implizit die aktuelle Zeile des Cursors in die definierten Variablen zu holen.


DECLARE
cursor payment_cursor is
select cust_id, payment, total_due from payment_table;
cust_id payment_table.cust_id%TYPE;
payment payment_table.payment%TYPE;
total_due payment_table.total_due%TYPE;
BEGIN
FOR pay_rec IN payment_cursor LOOP
IF pay_rec.payment < pay_rec.total_due THEN
insert into underpay_table
values (pay_rec.cust_id, 'STILL OWES');
END IF;
END LOOP;
END;


Dieses Beispiel durchläuft den Cursor mit einer FOR-Schleife. Die FOR-Schleife schließt in Verbindung mit einem Cursor die Befehle OPEN, FETCH und CLOSE ein, so daß man auf diese Befehle verzichten kann. Beachten Sie, daß auch das Attribut %NOTFOUND fehlt. Dieses Attribut ist implizit in der FOR-Schleife enthalten. Demzufolge liefert dieses und das vorherige Beispiel die gleichen Ergebnisse.


Der EXCEPTION-Abschnitt

Der EXCEPTION-Abschnitt ist ein optionaler Teil eines PL/SQL-Blocks. Wenn dieser Abschnitt fehlt und Fehler auftreten, wird der Block beendet. Bestimmte Fehler rechtfertigen aber nicht die unmittelbare Beendigung eines Blocks, so daß man mit dem EXCEPTION-Abschnitt spezielle Fehler oder benutzerdefinierte Ausnahmen in einer ordnungsgemäßen Weise behandeln kann. Exceptions (deutsch: Ausnahmen) können benutzerdefiniert sein, obwohl viele Exceptions bereits durch Oracle vordefiniert sind.



Exceptions auslösen

Exceptions werden in einem Block mit dem Befehl RAISE ausgelöst. Dabei kann der Programmierer explizit Exceptions auslösen, während interne Datenbankfehler automatisch - oder implizit - vom Datenbankserver ausgelöst werden.


Dieser Block zeigt die Grundlagen für das explizite Auslösen einer Exception. Zuerst wird der Exceptionname mit der Anweisung EXCEPTION deklariert. Im PROCEDURE-Abschnitt löst ein RAISE-Befehl die Exception aus, wenn eine gegebene Bedingung erfüllt ist. Die RAISE-Operation referenziert dann den EXCEPTION-Abschnitt des Blocks, wo die entsprechenden Anweisungen zur Fehlerbehandlung (oder andere Aktionen) stehen.


Exceptions behandeln

Das obige Beispiel hat eine Exception im EXCEPTION-Abschnitt des Blocks behandelt. In PL/SQL kann man problemlos auf Fehler reagieren und mit Hilfe von Exceptions den PL/SQL-Block entweder mit einem bekannten Fehler fortsetzen oder auf sanfte Weise beenden.


Dieses Beispiel zeigt, wie der EXCEPTION-Block aussehen könnte, wenn man mehrere Exceptions zu behandeln hat. Das Beispiel erwartet zwei Exceptions (Exception1 und Exception2), wenn dieser Block gestartet wird. Die Anweisung WHEN OTHERS bewirkt die Ausführung von Anweisung3, wenn keine anderen Exceptions auftreten, während der Block abgearbeitet wird. Die Klausel WHEN OTHERS erlaubt die Kontrolle über alle Fehler, die innerhalb des Blocks auftreten.


Einen PL/SQL-Block ausführen

PL/SQL-Anweisungen werden normalerweise mit einem Host-Editor erzeugt und wie normale SQL-Skript-Dateien ausgeführt. In PL/SQL ist jede Anweisung in einem Block mit einem Semikolon abzuschließen - angefangen bei Variablenzuweisungen bis zu Befehlen der Datenmanipulation. Der Schrägstrich (/) ist hauptsächlich in SQL-Skript-Dateien zu finden, PL/SQL beendet mit dem Schrägstrich aber auch einen Block in einer Skript-Datei. Ein PL/SQL-Block läßt sich am einfachsten mit dem Befehl START ausführen, den man auch als STA oder @ abkürzen kann.


Eine Skript-Datei in PL/SQL könnte etwa folgendermaßen aussehen:


Die PL/SQL-Skriptdatei führen Sie folgendermaßen aus:


SQL> start proc1


oder


SQL> sta proc1


oder


SQL> @proc1


PL/SQL-Skript-Dateien können mit dem Befehl START oder dem Zeichen @ ausgeführt werden. PL/SQL-Skript-Dateien lassen sich auch aus anderen PL/SQL-Dateien, Shell-Skripts oder Programmen aufrufen.


Ausgaben anzeigen

Insbesondere bei der Behandlung von Exceptions möchte man die Benutzer über die ablaufenden Vorgänge informieren. In der Ausgabe lassen sich einerseits Daten anzeigen, andererseits aber auch eigene Fehlermeldungen, die für den Benutzer sicherlich nützlicher sind als kryptische Fehlernummern. Sollte die Fehlermeldung zu kompliziert sein, können Sie den Benutzer auch bitten, sich mit dem Datenbank-Administrator in Verbindung zu setzen.


PL/SQL bietet zwar keine direkten syntaktischen Mittel für eine Anzeige, erlaubt aber den Aufruf eines Pakets aus einem Block heraus, um diese Funktion zu realisieren. Das betreffende Paket heißt DBMS_OUTPUT.


EXCEPTION
WHEN zero_divide THEN
DBMS_OUTPUT.put_line('Fehler: Division durch 0. Bitte DBA kontaktieren.');


ZERO_DIVIDE ist eine von Oracle vordefinierte Exception. Die gebräuchlichsten Fehler, die während der Programmabarbeitung auftreten, sind als Exceptions vordefiniert und werden implizit ausgelöst (das heißt Sie brauchen den Fehler nicht im PROCEDURE-Abschnitt des Blocks auslösen).

Wenn Sie den Block mit


SQL> @block1


ausführen und die Exception während der Abarbeitung des Blocks auftritt, erhalten Sie die Fehlermeldung:


Fehler: Division durch 0. Bitte DBA kontaktieren.

PL/SQL-Prozedur wurde erfolgreich abgeschlossen.


Sieht diese Meldung nicht freundlicher aus als:


SQL> @block1
begin
*

FEHLER in Zeile 1:
ORA-01476: Divisor ist Null
ORA-06512: in Zeile 20



Transaktionssteuerung in PL/SQL

In Lektion 11 haben wir die Befehle zur Transaktionssteuerung COMMIT, ROLLBACK und SAVEPOINT behandelt. Mit diesen Befehlen kann der Programmierer steuern, wann und wie oft Transaktionen tatsächlich in die Datenbank zu übernehmen und wann sie rückgängig zu machen sind.


Das Gute an PL/SQL ist, daß sich die Befehle zur Transaktionssteuerung automatisieren lassen. Die manchmal lästige Überwachung umfangreicher Transaktionen entfällt damit.



Alles zusammen

Bisher haben Sie eine Einführung in PL/SQL erhalten, sind mit den unterstützten Datentypen vertraut und kennen die wesentlichen Charakteristika eines PL/SQL-Blocks. Sie wissen, wie man lokale Variablen, Konstanten und Cursor deklariert. Außerdem haben Sie gesehen, wie man SQL im PROCEDURE-Abschnitt einbettet, Cursor manipuliert und Exceptions auslöst. Die grundsätzlichen Verfahren zur Behandlung von Ausnahmen im EXCEPTION-Abschnitt des Blocks kennen Sie ebenfalls. Nunmehr sind Sie darauf vorbereitet, einige praktische Beispiele durchzuarbeiten und Blöcke von BEGIN bis END zu erstellen. Am Ende dieses Abschnitts sollten Sie wissen, wie die Teile eines PL/SQL-Blocks miteinander interagieren.



Beispiele für Tabellen und Daten

Um PL/SQL-Blöcke zu erstellen, verwenden wir an dieser Stelle zwei Tabellen. ZAHLUNGEN speichert den Namen des Kunden, wieviel er bezahlt hat und wie hoch seine Restschuld ist. ZAHLUNG_STATUS enthält noch keinerlei Daten. Diese werden in die Tabelle entsprechend den Bedingungen in der Tabelle ZAHLUNGEN eingefügt.


SQL> SELECT *
2 FROM ZAHLUNGEN;


KUN ZAHLG SCHULD
--- --------- ---------
ABC 90,5 150,99
AAA 79 79
BBB 950 1000
CCC 27,5 27,5
DDD 350 500,95
EEE 67,89 67,89
FFF 555,55 455,55
GGG 122,36 122,36
HHH 26,75 0

9 Zeilen ausgewählt.


SQL> DESCRIBE ZAHLUNG_STATUS


Name Null? Type
------------------------------- -------- ----
KUND_NR NOT NULL CHAR(3)
STATUS NOT NULL VARCHAR2(15)
SOLL NUMBER(8,2)
HABEN NUMBER(8,2)


Der Oracle-SQL-Befehl DESCRIBE zeigt die Struktur einer Tabelle an, ohne daß man dazu den Systemkatalog abfragen muß. DESCRIBE und andere Befehle von Oracle SQL*Plus behandelt Tag 20.


Ein einfacher PL/SQL-Block

Das als Beispiel verwendete PL/SQL-Skript (block1.sql) sieht folgendermaßen aus:


set serveroutput on
BEGIN
DECLARE
AmtZero EXCEPTION;
cCustId ZAHLUNGEN.KUND_NR%TYPE;
fPayment ZAHLUNGEN.ZAHLG%TYPE;
fTotalDue ZAHLUNGEN.SCHULD%TYPE;
cursor ZAHLG_CURSOR is
select KUND_NR, ZAHLG, SCHULD
from ZAHLUNGEN;
fOverPaid number(8,2);
fUnderPaid number(8,2);
BEGIN
open ZAHLG_CURSOR;
loop
fetch ZAHLG_CURSOR into
cCustId, fPayment, fTotalDue;
exit when ZAHLG_CURSOR%NOTFOUND;
if ( fTotalDue = 0 ) then
raise AmtZero;
end if;
if ( fPayment > fTotalDue ) then
fOverPaid := fPayment - fTotalDue;
insert into ZAHLUNG_STATUS (KUND_NR, STATUS, HABEN)
values (cCustId, 'Zuviel bezahlt', fOverPaid);
elsif ( fPayment < fTotalDue ) then
fUnderPaid := fTotalDue - fPayment;
insert into ZAHLUNG_STATUS (KUND_NR, STATUS, SOLL)
values (cCustId, 'Restschuld', fUnderPaid);
else
insert into ZAHLUNG_STATUS
values (cCustId, 'Bezahlt', null, null);
end if;
end loop;
close ZAHLG_CURSOR;
EXCEPTION
when AmtZero then
DBMS_OUTPUT.put_line('Fehler: Betrag ist 0. Bitte Supervisor kontaktieren.');
when OTHERS then
DBMS_OUTPUT.put_line('Unbekannter Fehler. Bitte DBA konsultieren.');
END;
END;
/


Der DECLARE-Abschnitt definiert sechs lokale Variablen sowie einen Cursor namens ZAHLG_CURSOR. Der PROCEDURE-Abschnitt beginnt mit der zweiten BEGIN-Anweisung. Als erstes wird hier der Cursor geöffnet und eine Schleife gestartet. Der FETCH-Befehl übergibt die aktuellen Werte im Cursor in die Variablen, die im DECLARE-Abschnitt definiert wurden. Solange die Schleife Datensätze im Cursor findet, vergleicht die Anweisung den von einem Kunden bezahlten Betrag mit der gesamten Restschuld. Mehrzahlungen und Zahlungsverzug werden entsprechend der gezahlten Beträge berechnet. Dann übernimmt das Programm die berechneten Beträge in die Tabelle ZAHLUNG_STATUS. Die Schleife terminiert, und der Cursor wird geschlossen. Der EXCEPTION-Abschnitt behandelt Fehler, die während der Verarbeitung auftreten können.

Sehen wir uns nun an, was beim Start des PL/SQL-Skripts passiert.


SQL> @block1


Fehler: Betrag ist 0. Bitte Supervisor kontaktieren.

PL/SQL-Prozedur wurde erfolgreich abgeschlossen.


Diese Meldung zeigt, daß in der Spalte für die Gesamtschuld ein falscher Wert aufgetreten ist. Damit können Sie den Betrag korrigieren und das Skript erneut starten.


SQL> UPDATE ZAHLUNGEN
2 SET SCHULD = 26.75
3 WHERE KUND_NR = 'HHH';

1 Zeile wurde aktualisiert.

SQL> COMMIT;

Transaktion mit COMMIT abgeschlossen.

SQL> TRUNCATE TABLE ZAHLUNG_STATUS;

Tabelle mit TRUNCATE geleert.


Dieses Beispiel löscht den Inhalt der Tabelle ZAHLUNG_STATUS mit TRUNCATE TABLE. Der nächste Start des PL/SQL-Skripts füllt die Tabelle erneut. Die Anweisung TRUNCATE TABLE können Sie auch in Ihren PL/SQL-Block aufnehmen.

SQL> @block1

PL/SQL-Prozedur wurde erfolgreich abgeschlossen.


Nun können Sie aus der Tabelle ZAHLUNG_STATUS auswählen und die Zahlungsmoral für jeden Kunden anzeigen.


SQL> SELECT *
2 FROM ZAHLUNG_STATUS
3 ORDER BY STATUS;
KUN STATUS SOLL HABEN
--- --------------- --------- ---------
AAA Bezahlt
CCC Bezahlt
GGG Bezahlt
HHH Bezahlt
EEE Bezahlt
ABC Restschuld 60,49
DDD Restschuld 150,95
BBB Restschuld 50
FFF Zuviel bezahlt 100

9 Zeilen ausgewählt.


In die Tabelle ZAHLUNG_STATUS wird für jede Datenzeile, die in der Tabelle ZAHLUNGEN enthalten ist, eine Zeile eingefügt. Wenn der Kunde mehr als den geforderten Betrag bezahlt hat, kommt die Differenz in die Spalte HABEN. Hat der Kunde weniger als den Rechnungsbetrag bezahlt, erfolgt ein Eintrag in die Spalte SOLL. Bei vollständiger Bezahlung bleiben beide Spalten leer.


Ein anderes Programm

Dieses Beispiel arbeitet mit einer Tabelle namens LOHN:


SQL> DESC LOHN


Name Null? Type
------------------------------- -------- ----
NAME VARCHAR2(20)
ART VARCHAR2(3)
TARIF NUMBER(8,2)
SEIT DATE
TARIF_ALT NUMBER(8,2)


Sehen Sie sich zunächst die Daten an:


SQL> SELECT *
2 FROM LOHN
3 ORDER BY ART, TARIF DESC;


NAME ART TARIF SEIT TARIF_ALT
-------------------- --- --------- -------- ---------
CHRISSY ZOES GEH 50000 01.01.97
CLODE EVANS GEH 42150 01.03.97
JOHN SMITH GEH 35000 15.06.96
KEVIN TROLLBERG GEH 27500 15.06.96
SANDRA SAMUELS STD 12,5 01.01.97
ROBERT BOBAY STD 11,5 15.05.96
KEITH JONES STD 10 31.10.96
SUSAN WILLIAMS STD 9,75 01.05.97

8 Zeilen ausgewählt.


Die Situation: Der Umsatz ist gestiegen. Alle Mitarbeiter, die in den letzten sechs Monaten keine Gehaltserhöhung erhalten haben, werden heute damit bedacht. Alle in Frage kommenden stundenweise Beschäftigten erhalten eine 4prozentige Steigerung, und alle in Frage kommenden Gehaltsempfänger eine 5prozentige Erhöhung.


Heute ist:


SQL> SELECT SYSDATE
2 FROM DUAL;

SYSDATE
--------
12.12.97


Bevor wir den nächsten PL/SQL-Block untersuchen, führen wir eine manuelle Auswahl aus der Tabelle LOHN durch und zeigen die Mitarbeiter an, die eine Gehaltserhöhung erhalten sollten.


SQL> SELECT NAME, ART, TARIF, SEIT,
2 'JA' ANSPRUCH
3 FROM LOHN
4 WHERE SEIT < SYSDATE - 180
5 UNION ALL
6 SELECT NAME, ART, TARIF, SEIT,
7 'NEIN' ANSPRUCH
8 FROM LOHN
9 WHERE SEIT >= SYSDATE - 180
10 ORDER BY 2, 3 DESC;


NAME ART TARIF SEIT ANSP
-------------------- --- --------- -------- ----
CHRISSY ZOES GEH 50000 01.08.97 NEIN
CLODE EVANS GEH 42150 01.10.97 NEIN
JOHN SMITH GEH 35000 15.01.97 JA
KEVIN TROLLBERG GEH 27500 15.01.97 JA
SANDRA SAMUELS STD 12,5 01.08.97 NEIN
ROBERT BOBAY STD 11,5 15.12.96 JA
KEITH JONES STD 10 31.05.97 JA
SUSAN WILLIAMS STD 9,75 01.12.97 NEIN

8 Zeilen ausgewählt.


Die Spalte ANSPRUCH kennzeichnet die Mitarbeiter, die für eine Erhöhung in Frage kommen. Das PL/SQL-Skript sieht folgendermaßen aus:


set serveroutput on
BEGIN
DECLARE
UnknownPayType exception;
cursor LOHN_CURSOR is
select NAME, ART, TARIF, SEIT,
sysdate, rowid
from LOHN;
IndRec LOHN_CURSOR%ROWTYPE;
cOldDate date;
fNewPay number(8,2);
BEGIN
open LOHN_CURSOR;
loop
fetch LOHN_CURSOR into IndRec;
exit when LOHN_CURSOR%NOTFOUND;
cOldDate := sysdate - 180;
if (IndRec.ART = 'GEH') then
fNewPay := IndRec.TARIF * 1.05;
elsif (IndRec.ART = 'STD') then
fNewPay := IndRec.TARIF * 1.04;
else
raise UnknownPayType;
end if;
if (IndRec.SEIT < cOldDate) then
update LOHN
set TARIF = fNewPay,
TARIF_ALT = IndRec.TARIF,
SEIT = IndRec.sysdate
where rowid = IndRec.rowid;
commit;
end if;
end loop;
close LOHN_CURSOR;
EXCEPTION
when UnknownPayType then
dbms_output.put_line('=======================');
dbms_output.put_line('Fehler: Programm abgebrochen.');
dbms_output.put_line('Unbekannte Zahlungsart für: ' || IndRec.Name);
when others then
dbms_output.put_line('Fehler bei Verarbeitung. Bitte DBA kontaktieren.');
END;
END;
/


Sind Sie sicher, daß Sie vier Mitarbeitern eine Gehaltserhöhung geben wollen? (Die letzte SELECT-Anweisung zeigt vier JA-Werte in der Spalte ANSPRUCH.) Warum eigentlich nicht? Die entsprechende Anhebung können Sie zuweisen, indem Sie das PL/SQL-Skript namens BLOCK2.SQL ausführen:


SQL> @block2

PL/SQL-Prozedur wurde erfolgreich abgeschlossen.


Mit einer einfachen Auswahl können Sie sich davon überzeugen, daß die Änderungen an TARIF der in Frage kommenden Personen vorgenommen wurden:


SQL> SELECT *
2 FROM LOHN
3 ORDER BY ART, TARIF DESC;


NAME ART TARIF SEIT TARIF_ALT
-------------------- --- --------- -------- ---------
CHRISSY ZOES GEH 50000 01.08.97
CLODE EVANS GEH 42150 01.10.97
JOHN SMITH GEH 36750 13.12.97 35000
KEVIN TROLLBERG GEH 28875 13.12.97 27500
SANDRA SAMUELS STD 12,5 01.08.97
ROBERT BOBAY STD 11,96 13.12.97 11,5
KEITH JONES STD 10,4 13.12.97 10
SUSAN WILLIAMS STD 9,75 01.12.97

8 Zeilen ausgewählt.


Vier Mitarbeiter haben eine Gehaltserhöhung erhalten. Ein Vergleich mit der Ausgabe der anfänglichen SELECT-Anweisung zeigt die Änderungen. Der aktuelle Tarif spiegelt die Gehaltserhöhung wider. Der alte Tarif wurde in die Spalte TARIF_ALT übertragen und das Datum für das Inkrafttreten des neuen Tarifs (Spalte SEIT) auf das heutige Datum aktualisiert. Bei den nicht für eine Gehaltserhöhung in Frage kommenden Personen hat das Programm keine Änderungen vorgenommen.

Moment mal - es gab noch keine Möglichkeit, die Wirkung der definierten Exception zu sehen. Um den EXCEPTION-Abschnitt zu testen, fügt man eine ungültige Zahlungsweise (Spalte ART) in die Tabelle LOHN ein.


SQL> insert into LOHN values
2 ('JEFF JENNINGS','WOE',71.50,'01.08.97',null);

1 Zeile wurde erstellt.


Nun kommt der Moment der Wahrheit:


SQL> @block2
=======================
Fehler: Programm abgebrochen.
Unbekannte Zahlungsart für: JEFF JENNINGS

PL/SQL-Prozedur wurde erfolgreich abgeschlossen.


Die Fehlermeldung weist darauf hin, daß die Zahlungsweise bei JEFF JENNINGS einen Wert enthält, der von GEH oder STD abweicht. Die Exception wurde demnach mit einer Fehlermeldung behandelt.


Gespeicherte Prozeduren, Pakete und Trigger

Mit Hilfe von PL/SQL kann man gespeicherte Objekte erzeugen, um das ständige Eingeben gleichbleibenden Codes zu vermeiden. Prozeduren sind Codeblöcke, die eine bestimmte Aufgabe ausführen. Verwandte Prozeduren lassen sich in einem sogenannten Paket speichern. Ein Trigger ist ein Datenbankobjekt, das bei anderen Transaktionen zum Einsatz kommt. Beispielsweise kann man einen Trigger auf der Tabelle AUFTRAEGE einrichten, der Daten in eine Tabelle PROTOKOLL einfügt, wenn die Tabelle AUFTRAEGE Daten erhält. Die nächsten drei Abschnitte zeigen die grundlegende Syntax dieser Objekte.



PROCEDURE


PACKAGE


TRIGGER

Das folgende Beispiel fügt über einen Trigger eine Datenzeile in eine Transaktionstabelle ein, wenn die Tabelle LOHN aktualisiert wird. Die Tabelle TRANSAKTION hat folgendes Aussehen:


SQL> describe TRANSAKTION


Name Null? Type
------------------------------- -------- ----
AKTION VARCHAR2(10)
NAME VARCHAR2(20)
TARIF_ALT NUMBER(8,2)
TARIF_AKT NUMBER(8,2)
SEIT DATE


Als Beispiel verwenden wir die folgende Datenzeile:


SQL> select *
2 from LOHN
3 where name = 'JEFF JENNINGS';

NAME ART TARIF SEIT TARIF_ALT
-------------------- --- --------- -------- ---------
JEFF JENNINGS WOE 71,5 01.08.97

1 Zeile wurde ausgewählt.


Erzeugen Sie nun einen Trigger:


SQL> CREATE TRIGGER LOHN_TRIGGER
2 AFTER UPDATE ON LOHN
3 FOR EACH ROW
4 BEGIN
5 INSERT INTO TRANSAKTION VALUES
6 ('ART AEND', :new.name, :old.tarif,
7 :new.tarif, :new.seit);
8 END;
9 /

Trigger wurde erstellt.


Im letzten Schritt aktualisieren wir die Tabelle LOHN, um den Trigger auszulösen.


SQL> update LOHN
2 set TARIF = 15.50,
3 SEIT = sysdate
4 where name = 'JEFF JENNINGS';

1 Zeile wurde aktualisiert.

SQL> select *
2 from LOHN
3 where name = 'JEFF JENNINGS';

NAME ART TARIF SEIT TARIF_ALT
-------------------- --- --------- -------- ---------
JEFF JENNINGS WOE 15,5 13.12.97

1 Zeile wurde ausgewählt.

SQL> select *
2 from TRANSAKTION;

AKTION NAME TARIF_ALT TARIF_AKT SEIT
---------- -------------------- --------- --------- --------
ART AEND JEFF JENNINGS 71,5 15,5 13.12.97

1 Zeile wurde ausgewählt.


In der Tabelle LOHN enthält die Spalte TARIF_ALT den Wert NULL, während in der Tabelle TRANSAKTION in der Spalte TARIF_ALT ein Wert erscheint. Das ist nicht ganz so kompliziert, wie es auf den ersten Blick scheinen mag. Die Tabelle LOHN braucht keinen Eintrag für TARIF_ALT, da ein Stundenlohn von 71.50 offensichtlich einen fehlerhaften Betrag darstellt. Statt dessen haben wir den Wert für TARIF_ALT in die Tabelle TRANSAKTION eingefügt, da die Aktualisierung eine Transaktion darstellt und die Tabelle TRANSAKTION alle Transaktionen bezüglich der Tabelle LOHN protokollieren soll.

Wenn Sie sich in der Netzwerktechnologie auskennen, sind Ihnen sicherlich die Ähnlichkeiten der gespeicherten Prozeduren bei PL/SQL und Java aufgefallen. Es sei aber auf einige Unterschiede hingewiesen. PL/SQL ist eine Erweiterung von Standard-SQL und implementiert die Befehle einer prozeduralen Sprache. Java ist eine modernere Sprache als PL/SQL und erlaubt dem Programmierer, komplexere Programme zu schreiben, als es mit PL/SQL möglich ist. PL/SQL basiert auf der Datenbank-orientierten Funktionalität von SQL; Java zielt mehr auf CPU-intensive Programme ab. Die meisten prozeduralen Sprachen wie zum Beispiel PL/SQL sind speziell auf die jeweilige Plattform ausgerichtet. Die Weiterentwicklung der prozeduralen Sprachen wird ein höheres Niveau der Standardisierung über verschiedene Plattformen hinweg bringen.


Zusammenfassung

PL/SQL erweitert die Funktionalität von Standard-SQL. Die Basiskomponenten von PL/SQL realisieren die gleichen Funktionen wie bei einer Sprache der dritten Generation. Lokale Variablen unterstützen dynamischen Code, das heißt, Werte innerhalb eines Blocks können sich in Abhängigkeit von Benutzereingaben, angegebenen Bedingungen oder dem Inhalt eines Cursors ändern. PL/SQL arbeitet mit Anweisungen zur Programmsteuerung, die denen in Standardprogrammiersprachen ähnlich sind. IF...THEN-Anweisungen und Schleifen erlauben die Auswertung nach bestimmten Bedingungen. Mit Schleifen kann man durch den Inhalt eines definierten Cursors scrollen.


In professionellen Programmen sollte man der Fehlerbehandlung besondere Aufmerksamkeit schenken. Mit den Exceptions (Ausnahmen) von PL/SQL läßt sich das Verhalten eines Programms steuern, wenn syntaktische oder logische Fehler auftreten. Zahlreiche Exceptions - wie zum Beispiel Fehler bei Division durch Null - sind bereits vordefiniert. Während des Programmlaufs kann man Exceptions jederzeit nach spezifizierten Bedingungen auslösen und mit geeigneten Maßnahmen je nach Vorstellung des PL/SQL-Programmierers behandeln.


Lektion 18 hat auch einige praktische Einsatzfälle von PL/SQL gezeigt. Datenbankobjekte wie Trigger, gespeicherte Prozeduren und Pakete können viele Funktionen automatisieren. Die heutigen Beispiele setzen einige der Konzepte um, die wir in den vorangegangenen Tagen behandelt haben.



Fragen & Antworten

Frage:

Wurde in Lektion 18 alles behandelt, was ich über PL/SQL wissen muß?

Antwort:

Bei weitem nicht. Die heutige Einführung hat nur die wichtigsten Konzepte von PL/SQL gestreift. Wir wollten lediglich die wesentlichen Elemente hervorheben, um Ihnen grundlegende Kenntnisse zu PL/SQL zu vermitteln.

Frage:

Kann ich auch ohne PL/SQL auskommen?

Antwort:

Natürlich. Um aber die mit PL/SQL erreichbaren Ergebnisse zu erzielen, müssen Sie weit mehr Zeit in die Codierung einer Sprache der dritten Generation investieren. Wenn Sie nicht mit Oracle arbeiten, sollten Sie sich anhand Ihrer Dokumentation kundig machen, ob es in Ihrer Datenbank ähnliche Möglichkeiten wie mit PL/SQL gibt.


Workshop


Kontrollfragen

1. Wie setzt man einen Datenbanktrigger ein?


2. Können verwandte Prozeduren zusammen gespeichert werden?


3. Richtig oder falsch: In PL/SQL kann man die Anweisungen der Datenmanipulationssprache verwenden.


4. Richtig oder falsch: In PL/SQL kann man die Anweisungen der Datendefinitionssprache verwenden.


5. Gehört die Textausgabe unmittelbar zur Syntax von PL/SQL?


6. Nennen Sie die drei Hauptbestandteile einer PL/SQL-Anweisung.


7. Nennen Sie die Befehle, die zur Cursorsteuerung gehören.



Übungen

1. Deklarieren Sie eine Variable namens Stundenlohn, die einen größten Wert von 99.99/Stunde akzeptiert.


2. Definieren Sie einen Cursor mit allen Datensätzen der Tabelle KUNDEN, die in der Spalte STADT den Eintrag INDIANAPOLIS enthalten.


3. Definieren Sie eine Exception namens UnbekannterCode.


4. Schreiben Sie eine Anweisung, die BETRAG in der Tabelle BETRAG_TABELLE auf 10 setzt, wenn CODE gleich A ist, BETRAG auf 20 setzt, wenn CODE gleich B ist, und eine Exception namens UnbekannterCode auslöst, wenn CODE weder A noch B ist. Die Tabelle hat eine Zeile.



Ein Imprint des Markt&Technik Buch- und Software-Verlag GmbH.
Elektronische Fassung des Titels: SQL in 21 Tagen, ISBN: 3-8272-2020-3


vorheriges KapitelTop Of PageInhaltsverzeichnisIndexInfoseitenächstes Kapitel