Universität Duisburg-Essen Informationssysteme Prof. Dr.-Ing. N. Fuhr



Ähnliche Dokumente
Universität Duisburg-Essen Informationssysteme Prof. Dr.-Ing. N. Fuhr. Praktikum Datenbanken / DB2 Woche 8: Trigger, SQL-PL

Universität Duisburg-Essen Informationssysteme Prof. Dr.-Ing. N. Fuhr

User Defined Functions

Uni Duisburg-Essen Fachgebiet Informationssysteme Prof. Dr. N. Fuhr. Praktikum: Datenbanken Woche 7: Noch mehr SQL

User Defined Functions

Uni Duisburg-Essen Fachgebiet Informationssysteme Prof. Dr. N. Fuhr. Praktikum Datenbanken / DB2

Mengenvergleiche: Alle Konten außer das, mit dem größten Saldo.

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Dipl. Inf. Dipl. Math. Y. Orkunoglu Datum:

Erwin Grüner

Programmierkurs Java

Prozedurale Datenbank- Anwendungsprogrammierung

Übungsblatt 8- Lösungsvorschlag

mit Musterlösungen Prof. Dr. Gerd Stumme, Dipl.-Inform. Christoph Schmitz 11. Juni 2007

Views in SQL. 2 Anlegen und Verwenden von Views 2

Einführung in die Programmierung

Professionelle Seminare im Bereich MS-Office

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Dynamisches SQL. Folien zum Datenbankpraktikum Wintersemester 2009/10 LMU München

SQL für Trolle. mag.e. Dienstag, Qt-Seminar

Uni Duisburg-Essen Fachgebiet Informationssysteme Prof. Dr. N. Fuhr

5. Tutorium zu Programmieren

Suchmaschinen. Universität Augsburg, Institut für Informatik SS 2014 Prof. Dr. W. Kießling 23. Mai 2014 Dr. M. Endres, F. Wenzel Lösungsblatt 6

Informatik 12 Datenbanken SQL-Einführung

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2015/16. Vorbereitende Aufgaben

Objektorientierte Programmierung

Modellierung und Programmierung 1

Whitepaper. Produkt: combit Relationship Manager. Datensatzhistorie mit dem SQL Server 2000 und combit GmbH Untere Laube Konstanz

Wir arbeiten mit Zufallszahlen

Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Abfragen: Grundbausteine

Datenbanksysteme 2 Frühjahr-/Sommersemester Mai 2014

Übungen Programmieren 1 Felix Rohrer. Übungen

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

1 Vom Problem zum Programm

Informatik Grundlagen, WS04, Seminar 13

Beispiel 1: Filmdatenbank

Grundlagen der Programmierung Prof. H. Mössenböck. 3. Verzweigungen

Details zu den Ausdrücken nach FROM, WHERE, GROUP BY und HAVING finden Sie in den Abschnitten über JOIN, WHERE und GROUP BY.

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

Oracle SQL Tutorium - Wiederholung DB I -

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

cs241: Datenbanken mit Übungen HS 2011

Universität Augsburg, Institut für Informatik WS 2006/2007 Dr. W.-T. Balke 27. Nov M. Endres, A. Huhn, T. Preisinger Lösungsblatt 5

Datenbanken Kapitel 2

Funktionale Programmierung mit Haskell

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: MORE Projects GmbH

Java 7. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Dezember 2011 JAV7

Druckerscriptsprache

1 topologisches Sortieren

Übungskomplex Felder (1) Eindimensionale Felder Mehrdimensionale Felder

DATENBANKEN SQL UND SQLITE VON MELANIE SCHLIEBENER

Java-Programmierung mit NetBeans

Vorlesung Dokumentation und Datenbanken Klausur

Einführung in die Java- Programmierung

Arge Betriebsinformatik GmbH & Co.KG, CAP News 40, Februar CAP-News 40

Übersicht Programmablaufsteuerung

Enigmail Konfiguration

Datentypen. Agenda für heute, 4. März, Pascal ist eine streng typisierte Programmiersprache

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Informationsblatt Induktionsbeweis

php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick Parameterübergabe...

Datenbanken für Online Untersuchungen

Kapitel 33. Der xml-datentyp. In diesem Kapitel: Der xml-datentyp 996 Abfragen aus xml-datentypen 1001 XML-Indizierung 1017 Zusammenfassung 1023

Fallbeispiel: Eintragen einer Behandlung

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

5. Übung: PHP-Grundlagen

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Labor 3 - Datenbank mit MySQL

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

Modul 122 VBA Scribt.docx

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Relationales Modell: SQL-DDL. SQL als Definitionssprache. 7. Datenbankdefinitionssprachen. Anforderungen an eine relationale DDL

Access [basics] Gruppierungen in Abfragen. Beispieldatenbank. Abfragen gruppieren. Artikel pro Kategorie zählen

Einführung in die Programmierung (EPR)

Summenbildung in Bauteiltabellen mit If Then Abfrage

SQL (Structured Query Language) Schemata Datentypen

Handbuch. NAFI Online-Spezial. Kunden- / Datenverwaltung. 1. Auflage. (Stand: )

Ist Fernsehen schädlich für die eigene Meinung oder fördert es unabhängig zu denken?

Übung Datenbanken in der Praxis. Datenmodifikation mit SQL

Anleitung über den Umgang mit Schildern

Rundung und Casting von Zahlen

4. BEZIEHUNGEN ZWISCHEN TABELLEN

SQL SQL. SQL = Structured Query Language (SEQUEL) IBM San Jose Research Laboratory SYSTEM R. Grundlagen der Datenbanksysteme I

Mediator 9 - Lernprogramm

Java Kurs für Anfänger Einheit 5 Methoden

1 Mathematische Grundlagen

P r o g r a m m a b l a u f s t e u e r u n g

Einführung in die Programmierung

Gesicherte Prozeduren

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Praktikum Ingenieurinformatik. Termin 2. Verzweigungen (if-else), printf und scanf, while-schleife

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

Visual Basic Basisbefehle Hinweis: Der Text in eckigen Klammern [ ] ist variabel, z.b. [var] => 5.3. Eckige Klammern sind stets wegzulassen!

Datenübernahme von HKO 5.9 zur. Advolux Kanzleisoftware

Dokumentation. Black- und Whitelists. Absenderadressen auf eine Blacklist oder eine Whitelist setzen. Zugriff per Webbrowser

Einfache Ausdrücke Datentypen Rekursive funktionale Sprache Franz Wotawa Institut für Softwaretechnologie

10.6 Programmier-Exits für Workitems

Transkript:

Betreuer: Sascha Kriewel, Tobias Tuttas Raum: LF 230 Bearbeitung: 23.-24. Juni 2008 Vorbereitungsaufgabe: Upload (als PDF) bis 19. Juni 2008 Präsenzaufgaben: Upload bis 29. Juni 2008 http://www.is.inf.uni-due.de/courses/dbp_ss08/abgabe/pre07.html Datum Team (Account) Aktuelle Informationen, Ansprechpartner, Material und Upload unter: http://www.is.inf.uni-due.de/courses/dbp_ss08/index.html Wochenziele In dieser Woche sollen einige fortgeschrittene SQL-Konzepte behandelt werden Konkret wird es um Indexe, benutzerdefinierte Funktionen, rekursive Anfragen und Trigger gehen. Für jedes dieser Konzepte wollen wir Beispiele entwickeln. Benutzerdefinierte Funktionen Über User Defined Functions (UDFs) lassen sich neue Datenbank-Funktionen implementieren. Einige vordefinierte Funktionen wie z.b. posstr oder locate haben wir bereits in früheren Wochen kennengelernt. So läßt sich das DBMS um anwendungsfallspezifische Funktionalitäten erweitern. Es wird dabei zwischen externen UDFs und SQL-UDFs unterschieden. Im Rahmen des Praktikums sollen nur letztere behandelt werden. Während externe Funktionen in einer seperaten Programmiersprache wie etwa C geschrieben werden, implementiert man SQL-UDFs in der SqlPl (SQL Programming Language). Man unterscheidet dabei zwischen UDFs mit skalarer, tupelwertiger und tabellenwertiger Rückgabe. Skalare UDFs liefern einen skalaren Wert zurück und lassen sich in Ausdrücken verwenden. Tupelwertige UDFs sind für benutzerdefinierte Typen interessant, und bleiben hier außen vor. Tabellenwertige UDFs können wie eine normale Tabelle in einer FROM-Klausel benutzt werden. Seite 1 von 16

SQL-UDFs können auf die Datenbank zugreifen und dürfen selbst SQL-Statements enthalten, dabei besitzen temporale Registerwerte innerhalb einer SQL-UDF stets einen konstanten Wert (d.h. tritt ein Zeitregister mehrfach in einer SQL-UDF auf, so hat es bei jedem Vorkommen den selben Wert). Mit Hilfe der Systemtabelle SYSCAT.FUNCTIONS kann man sich einen Überblick über vordefinierte und existierende benutzerdefinierte Funktionen verschaffen: -- alle Funktionen SELECT funcschema, funcname FROM syscat.functions -- nur benutzerdefinierte Funktionen SELECT funcschema, funcname FROM syscat.functions WHERE definer <> SYSIBM Die Tabelle SYSCAT.FUNCTIONS enthält neben Namen und Schema der Funktionen noch eine Reihe weiterer Informationen, wie man leicht sieht, wenn man describe table SYSCAT.FUNCTIONS ausführt. Erstellt wird eine benutzerdefinierte Funktion über das CREATE FUNCTION- Statement. Bevor wir uns einige Beispiele ansehen, zunächst eine kurze Einführung in die grundlegenden Konstrukte von SqlPl. S. 188, S. 254ff SQL Programming Language Die SqlPl ist im SQL99-Standard definiert, und ist eine sehr einfache Programmiersprache, die innerhalb eines DBMS benutzt werden kann. Insbesondere findet sie in Stored Procedures, Triggern und bei der Implementierung von SQL-UDFs Verwendung. Im Falle von Triggern und Funktionen werden die SqlPl-Anweisungen im DBMS abgelegt und bei Bedarf interpretiert. Dabei umfasst die SqlPl unter anderem die im Folgenden kurz beschriebenen Anweisungen. Prozeduren erlauben zusätzliche Kontroll-Statements, die hier aber zunächst nicht behandelt werden sollen. WICHTIG: Getrennt werden die einzelnen Anweisungen in SqlPl durch Semikolons. Daher muß man beachten, dass man Zeilen im CLP nicht mit einem Semikolon enden läßt (mit Ausnahme des tatsächlichen Ende des Statements), oder ein alternatives Terminierungszeichen benutzen. So erwartet die Kommandozeile beim Aufruf des CLP mit db2 -c -td@ z.b. das Zeichen @ als Ende einer Zeile. Seite 2 von 16

Um mehrere SqlPl-Statements zusammenzufassen, kann man im Rumpf einer Trigger- oder Funktionsdefinition einen mit BEGIN... END geklammerten Anweisungsblock benutzen. Dieses ist ausführlicher in der Dokumentation beschrieben, und sieht z.b. so aus: name: BEGIN ATOMIC DECLARE counter INTEGER; Anweisungen; END name Durch das Schlüsselwort ATOMIC wird festgelegt, dass bei Fehlern innerhalb des Anweisungsblocka alle Anweisungen des Blocks zurückgenommen werden (hiermit werden wir uns in der nächsten Woche näher beschäftigen). Variablen, die man innerhalb des Anweisungsblocks benutzen möchte, definiert man mit DECLARE. Dabei gibt man der Variable einen lokalen Namen, spezifiziert den Datentyp und definiert gegebenenfalls einen Default-Wert für die Variable (standardmäßig NULL). Durch das Label name ist es möglich, den benannten Block durch ein LEAVE- Statement zu verlassen. Außerdem kann das Label zur Qualifizierung von Variablen benutzt werden. S. 123 SQL-Statements Viele der üblichen SQL-Statements sind auch innerhalb von Funktionsdefinitionen erlaubt: das Fullselect, UPDATE oder DELETE mit Suchbedingung, INSERT und SET für Variablen. FOR Das FOR-Statement führt ein oder mehrere SQL-Statements für jedes Tupel einer Relation aus. Dabei kann die FOR-Schleife durch Voranstellung von label: benannt werden. Dieses Label kann dann in LEAVE- oder ITERATE-Statements benutzt werden. BEGIN DECLARE vollertitel CHAR(40); FOR t AS SELECT titel, jahr, budget FROM produktion DO SET vollertitel = t.titel ( t.jahr ) ; INSERT INTO einetabelle VALUES (vollertitel, t.budget); END FOR; END Das obige Beispiel benutzt den Operator zur Stringkonkatenation (Zusammenfügen zweier Zeichenketten zu einer neuen). S. 775 Seite 3 von 16

IF Das IF-Statement ermöglicht bedingte Ausführung von Statements. Die Anweisung wird ausgeführt, wenn die Suchbedingung zu true evaluiert. Liefert sie false oder unknown, dann wird stattdessen die nächste Suchbedingung hinter einem ELSEIF ausgeführt. Evaluiert keine Suchbedingung zu true, wird stattdessen der ELSE-Zweig ausgeführt. IF anzahl_postings < 10 THEN SET typ = Anfänger ; ELSEIF anzahl_postings < 100 THEN SET typ = Mitglied ; ELSEIF anzahl_postings < 1000 THEN SET typ = Seniormitglied ; ELSE SET typ = Profi ; END IF S. 782 IF folgen_gesamt > (SELECT count(*) FROM seriefolge WHERE serientitel = titel1 AND drehjahr = titel2) THEN RETURN unvollständig ; ELSE RETURN vollständig ; END IF WHILE Eine WHILE-Schleife wird solange durchlaufen, bis die angegebene Suchbedingung nicht mehr als true evaluiert. Bei jedem Durchlauf wird der Schleifenkörper ausgeführt. Dabei kann die WHILE-Schleife durch Voranstellung von label: benannt werden. Dieses Label kann in LEAVE- oder ITERATE-Statements benutzt werden. WHILE counter < 10 DO Schleifenkörper END WHILE S. 799 ITERATE Mit dem ITERATE-Statement verläßt man die Abarbeitung des aktuellen Schleifendurchlaufs und springt zum Anfang der benannten Schleife (FOR, LOOP, REPEAT oder WHILE) zurück. ITERATE schleifenname S. 784 Seite 4 von 16

LEAVE Mit dem LEAVE-Statement verläßt man vorzeitig eine benannte Schleife (FOR, LOOP, REPEAT, WHILE) oder einen Anweisungsblock. Dabei werden gegebenenfalls alle Cursor geschlossen, mit Ausnahme derer, welche die Ergebnisrelation definieren. (Über Cursor mehr in der nächsten Woche.) LEAVE schleifenname S. 785 RETURN Mit dem RETURN-Statement kann man aus einer Funktion herausspringen. Dabei muß ein Rückgabewert definiert werden, der mit dem Rückgabetyp der Funktion kompatibel ist. Bei Tabellenfunktionen muß ein Fullselect benutzt werden. RETURN substring(name,locate(name,, )) S. 794 RETURN SELECT name, todesdatum FROM person WHERE todesdatum IS NOT NULL Zuweisungen Über SET kann man innerhalb eines Anweisungsblock oder im Rumpf eines Kontroll- Statements Zuweisungen an Variables tätigen. SIGNAL Mit dem SIGNAL-Statement kann man einen SQL-Fehler oder eine SQL-Warnung werfen. Der erklärende Fehlertext darf maximal 70 Zeichen lang und kann auch eine Variable sein. Dabei gilt zur Benennung des SQL-Status: ein SQL-Status ist ein fünf Zeichen langer String aus Großbuchstaben und Ziffern, er darf nicht mit 00 beginnen (Erfolg), in Triggern oder Funktionen darf er nicht mit 01 (Warnung) oder 02 beginnen, ein SQL-Status, der nicht mit 00, 01 oder 02 beginnt, signalisiert einen Fehler, beginnt der String mit 0-6 oder A-H, so müssen die letzten drei Zeichen mit I-Z beginnen SIGNAL SQLSTATE 03ILJ SET MESSAGE_TEXT= Fehler: Illegales Jahr S. 796 Seite 5 von 16

Beispiele Skalare Funktion: Tangens Ein einfaches Beispiel für eine skalare Funktion ist die Berechnung des Tangens (aus der IBM DB2 Dokumentation): CREATE FUNCTION tan (x DOUBLE) RETURNS DOUBLE LANGUAGE SQL CONTAINS SQL DETERMINISTIC RETURN sin(x)/cos(x) Diese Funktion berechnet den Tangens zu einem Wert. Sie erwartet einen Eingabewert vom Datentyp DOUBLE, der intern den Variablennamen x erhält und liefert einen Ausgabewert ebenfalls vom Datentyp DOUBLE, der als Quotient aus den existierenden Funktionen Sinus und Kosinus berechnet wird. RETURNS definiert die erwartete Rückgabe, hier ein skalarer Wert vom Typ DOU- BLE LANGUAGE SQL signalisiert, dass die Funktion in SQL geschrieben ist CONTAINS SQL signalisiert, dass die Funktion nur nicht-lesende und nichtmodifizierende SQL-Statements benutzen darf, READS SQL DATA erlaubt auch lesende SQL-Statements DETERMINISTIC ist eine optionale Klausel und signalisiert, dass bei Aufruf mit den gleichen Parametern stets das gleiche Resultat geliefert wird (sonst benutzt man NON DETERMINISTIC) RETURN liefert schließlich das Ergebnis einer Berechnung zurück Aufgerufen würde die Funktion z.b. derart: SELECT tan(c) FROM (values (1)) t(c) Seite 6 von 16

Skalare Funktionen: Boolesche Operatoren DB2 kennt keinen Datentyp Boolean für Wahrheitswerte. Wir können uns aber eigene Funktionen schreiben, um diese Lücke zu schließen. Dazu kann man den Datentyp SMALLINT benutzen mit 1 für TRUE und 0 für FALSE. Die booleschen Operatoren AND, NOT und OR könnten dann durch folgende skalare Funktionen ausgedrückt werden: CREATE FUNCTION bool_and(x smallint, y smallint) RETURNS SMALLINT BEGIN ATOMIC IF x IS NULL OR y IS NULL THEN RETURN NULL; ELSEIF x =1 AND y = 1 THEN RETURN 1 ; ELSE RETURN 0; END IF; END CREATE FUNCTION bool_not(x smallint) RETURNS SMALLINT BEGIN ATOMIC IF x IS NULL THEN RETURN NULL; ELSEIF x=1 THEN RETURN 0; ELSE RETURN 1; END IF; END CREATE FUNCTION bool_or(x smallint, y smallint) RETURNS SMALLINT BEGIN ATOMIC IF x = 1 THEN RETURN 1; ELSEIF x = 0 THEN RETURN y; ELSEIF y = 1 THEN RETURN 1; ELSE RETURN NULL; END IF; END Die Schlüsselworte AND, OR und NOT dürfen nicht als Funktionsnamen benutzt werden, weshalb hier bool_and, bool_or und bool_not gewählt wurden. Man beachte, dass die Funktionen Werte vom Typ SMALLINT erwarten. Die Literale 1 und 0 werden standardmäßig als INTEGER interpretiert und müssen gegebenenfalls zunächst mittels der Funktion smallint() umgewandelt werden. Seite 7 von 16

Tabellenwertige Funktion Das letzte Beispiel zeigt eine tabellenwertige Funktion, die für einen bestimmten Film alle Schauspieler mit deren Namen und Vornamen liefert. CREATE FUNCTION schauspielerliste (filmtitel VARCHAR(200), filmjahr INTEGER) RETURNS TABLE (name VARCHAR(100),vorname VARCHAR(100)) LANGUAGE SQL READS SQL DATA NO EXTERNAL ACTION DETERMINISTIC RETURN SELECT name,vorname FROM schauspieler, spieltinfilm WHERE schauspieler.id = spieltinfilm.schauspielerid AND spieltinfilm.titel = filmtitel AND spieltinfilm.drehjahr = filmjahr RETURNS legt das Aussehen und Format der Rückgabetabelle fest READS SQL DATA ist nötig, da wir in dieser Funktion lesend auf zwei Tabellen, nämlich schauspieler und spieltinfilm zugreifen RETURN liefert nun das Ergebnis eines SELECTs zurück Eine tabellenwertige Funktion kann normal im FROM-Teil eines SELECT- Statements benutzt werden, wenn man sie in eine TABLE Klausel einschließt. Die Syntax sieht im Beispiel wie folgt aus: SELECT * FROM TABLE (schauspielerliste( Event Horizon,1997)) sl; Rekursive Anfragen In einem vollen SELECT-Statement ist es auch möglich, rekursive Anfragen zu stellen. Rekursive Anfragen sind solche Anfragen, die sich in ihrer Definition auf sich selbst beziehen. Derart kann man etwa die transitive Hülle eines Tupels oder Stücklisten berechnen. Ein kurzer Ausflug, um das Konzept der Rekursion zu erklären: Rekursion aus Wikipedia, der freien Enzyklopädie (http://de.wikipedia.org/wiki/rekursion) Rekursion bedeutet Selbstbezüglichkeit. Sie tritt immer dann auf, wenn etwas auf sich selbst verweist oder mehrere Dinge aufeinander, so dass merkwürdige Schleifen entstehen. So ist z.b. der Satz Dieser Satz ist unwahr rekursiv, da er von sich selber spricht. [...] Dabei ist Rekursion ein allgemeines Prinzip zur Lösung von Problemen, das in vielen Fällen zu eleganten mathematischen Lösungen db2s1e81.pdf, S. 601 Seite 8 von 16

führt. Als Rekursion bezeichnet man den Aufruf bzw. die Definition einer Funktion durch sich selbst. Ohne geeignete Abbruchbedingung geraten solche rückbezüglichen Aufrufe in einen sog. infiniten Regress [Endlosrekursion]. [...] Die Definition von rekursiv festgelegten Funktionen ist eine grundsätzliche Vorgehensweise in der funktionalen Programmierung. Ausgehend von einigen gegebenen Funktionen (wie zum Beispiel unten die Summen-Funktion) werden neue Funktionen definiert, mithilfe derer weitere Funktionen definiert werden können. Hier ein Beispiel für eine Funktion sum : N 0 N 0, die die Summe der ersten n Zahlen berechnet: { 0, falls n = 0 (Rekursionsbasis) sum(n) = sum(n 1) + n, falls n 1 (Rekursionsschritt)0 Bei einer rekursiven Anfrage (RA) muß man folgende Regeln beachten: Jedes Fullselect, das Teil einer RA ist, muß mit SELECT beginnen (aber nicht mit SELECT DISTINCT). Es darf nicht geschachelt sein. Als Vereinigung muss UNION ALL benutzt werden. Im WITH-Teil müssen Spaltennamen explizit angegeben werden. Das erste Fullselect in der ersten Vereinigung darf sich nicht auf die zu definierende Tabelle beziehen. Es bildet die Rekursionsbasis. Die Datentypen und Längen der Spalten der zu definierenden Tabelle werden durch die SELECT-Klausel der Rekursionsbasis festgelegt. Kein Fullselect in der rekursiven Definition darf eine Aggregatfunktion, eine GROUP BY- oder eine HAVING-Klausel enthalten. Die FROM-Klauseln in der rekursiven Definition dürfen höchstens eine Referenz auf die zu definierende Tabelle besitzen. Es dürfen keine Subqueries verwendet werden. Wenn die Daten Zyklen enthalten können, dann ist es möglich, dass durch eine RA eine Endlosrekursion erzeugt wird. Dann ist es wichtig, eine Abbruchbedingung zu definieren: Die zu definierende Tabelle muß ein Attribut enthalten, das durch eine INTEGER-Konstante initialisiert wird, und regelmäßig erhöht wird. In jeder WHERE-Klausel muß eine Prüfbedingung auftreten. Die Auswertung einer rekursiven Anfrage läuft wie folgt ab: Zuerst werden die Tupel der Rekursionsbasis berechnet, dann werden ausgehend von diesen Tupeln gemäß des zweiten Teils des Fullselects (nach dem UNION ALL) weitere Tupel berechnet. Dabei werden jedoch nur diejenigen Tupel aus der rekursiv definierten Relation verwendet, die beim letzten Berechnungsschritt neu hinzugekommen sind (beginnend also mit den Tupeln der Rekursionsbasis). Kamen in einem Berechnungsschritt keine neuen Tupel hinzu, so endet die Berechnung. Seite 9 von 16

Beispiel: Gegeben sei eine Tabelle mit Bauteilen, in denen die Komponten für Werkstücke festgehalten werden. Dabei können diese Komponenten selber wiederum aus Einzelteilen zusammengesetzt sein. CREATE TABLE bauteile ( stueck VARCHAR(8), komponente VARCHAR(8), menge INTEGER); Um nun zu ermitteln, welche Basiskomponenten insgesamt nötig sind, um ein Beispiel-Bauteil herzustellen, kann man eine rekursive Anfrage benutzen. In der folgenden RA ist die im ersten Teil der WITH-Klausel definierte Query rek die Rekursionsbasis, im zweiten Teil der WITH-Klausel folgt dann die Definition der Rekursion. Die so rekursiv definierte Ergebnisrelation wird dann im SELECT DISTINCT-Teil benutzt. WITH rek (stueck, komponente, menge) AS ( SELECT r.stueck, r.kompenente, r.menge FROM bauteile r WHERE r.stueck = Beispiel-Bauteil UNION ALL SELECT kind.stueck, kind.komponente, kind.menge FROM rek vater, bauteile kind WHERE vater.komponente = kind.stueck ) SELECT DISTINCT stueck, komponente, menge FROM rek ORDER BY stueck, komponente, menge Trigger Als Trigger (deutsch Auslöser) bezeichnet man in SQL eine Anweisungsfolge (eine Abfolge von Aktionen), die ausgeführt wird, wenn eine verändernde Anweisung auf einer bestimmten Tabelle ausgeführt werden soll. Wir erinnern uns aus früheren Übungen, dass verändernde Anweisungen für Tabellen DELETE, INSERT und UPDATE sind. Man kann Trigger zum Beispiel nutzen, um neu eingefügte oder zu verändernde Tupel auf ihre Gültigkeit bezüglich vorgegebener Bedingungen zu überprüfen, Werte zu generieren, in anderen Tabellen zu lesen (etwa zur Auflösung von Querverweisen) oder zu schreiben (etwa zur Protokollierung) Seite 10 von 16

Insbesondere kann man mit Triggern Regeln in der Datenbank modellieren. Einen Trigger erstellt man mit dem CREATE TRIGGER-Statement, mit DROP TRIGGER wird er gelöscht. Man kann Trigger entweder so schreiben, dass sie für jedes zu ändernde Tupel einmal (FOR EACH ROW) oder für jedes verändernde Statement einmal (FOR EACH STATEMENT) ausgeführt werden. Letzteres ist allerdings nur für die sogenannten AFTER-Trigger erlaubt, die im Anschluß an eine verändernde Operation tätig werden. In diesem Fall wird der Trigger auch dann abgearbeitet, wenn kein Tupel von dem DELETE- oder dem UPDATE-Statement betroffen ist. Über die REFERENCING-Klausel werden Namen für die Übergangsvariablen festgelegt: OLD AS name bzw. NEW AS name definiert name als Name für die Werte des betroffenen Tupels vor bzw. nach der Ausführung der auslösenden Operation. Entsprechend definieren OLD_TABLE AS identifier bzw. NEW_TABLE AS identifier diesen als Name für eine hypothetische Tabelle, welche die betroffenen Tupel vor bzw. nach der auslösenden Operation enthält. Dabei gilt : auslösendes Ereignis ROW-Trigger darf STATEMENT-Trigger und Zeitpunkt benutzen darf benutzen BEFORE INSERT NEW - BEFORE UPDATE OLD, NEW - BEFORE DELETE OLD - AFTER INSERT NEW, NEW_TABLE NEW_TABLE AFTER UPDATE OLD, NEW, OLD_TABLE, OLD_TABLE, NEW_TABLE NEW_TABLE AFTER DELETE OLD, OLD_TABLE OLD_TABLE S. 414 Über vorhandene Trigger auf einer Datenbank kann man die System-Tabelle SYSIBM.SYSTRIGGERS konsultieren: SELECT name,text FROM SYSIBM.SYSTRIGGERS Beispiel: Angenommen, wir führten eine Tabelle afps (Anzahl Folgen pro Serie), dann könnte ein Trigger für das Einfügen von neuen Tupeln in die Tabelle serienfolge eventuell derart aussehen: CREATE TRIGGER neue_folge AFTER INSERT ON serienfolge REFERENCING NEW AS neu FOR EACH ROW MODE DB2SQL UPDATE afps SET anzahl_folgen = anzahl_folgen + 1 WHERE neu.serientitel = afps.serientitel AND neu.drehjahr = afps.drehjahr Seite 11 von 16

Und ein Einfügen eines Tupels in serienfolge würde automatisch zu einem UP- DATE der Tabelle afps führen: INSERT INTO afps (serientitel, drehjahr, anzahl_folgen) VALUES ( Babylon 5 - The Telepath Tribes, 0); INSERT INTO serienfolge (serientitel, drehjahr, staffelnr, folgennr, folgentitel) VALUES ( Babylon 5 - The Telepath Tribes, 2007, 1, 1, Forget Byron ); INSERT INTO serienfolge (serientitel, drehjahr, staffelnr, folgennr, folgentitel) VALUES ( Babylon 5 - The Telepath Tribes, 2007, 1, 2, Bester s Best ); SELECT anzahl_folgen AS Anzahl FROM afps WHERE land= Babylon 5 - The Telepath Tribes ANZAHL ------ 2 Noch ein Beispiel: CREATE TRIGGER check_ausleihe NO CASCADE BEFORE INSERT ON ausleihe REFERENCING NEW AS neu FOR EACH ROW MODE DB2SQL IF neu.ausleihdatum > current date THEN SIGNAL SQLSTATE 75000 SET MESSAGE_TEXT = Ein Ausleihvorgang kann nicht im voraus eingefügt werden. ; END IF Dieser Trigger verbietet das Einfügen neuer Tupel in ausleihe, bei denen das Ausleihdatum in der Zukunft liegt. (Es sollen also nur bereits stattgefundene Ausleihvorgänge eingetragen werden.) Der Versuch führt zu einem Fehler und das Statement wird nicht ausgeführt. Index Ein Index ist ein Datenbankobjekt, das den Zugriff über bestimmte Attribute einer Tabelle beschleunigen soll und dies in den allermeisten Fällen auch tut. Man kann auch (UNIQUE)-Indexe verwenden, um die Einhaltung von Schlüsselbedingungen sicherzustellen. Seite 12 von 16

Werden bei der Tabellendefinition Primärschlüssel- (PRIMARY KEY) oder Sekundärschlüsselbedingungen (UNIQUE) angegeben, so legt DB2 selbständig Indexe an, um die Einhaltung dieser sicherzustellen. Ein einmal angelegter Index wird dann automatisch bei Änderungen an den Inhalten der entsprechenden Tabelle gepflegt. Dies ist natürlich mit einem erhöhten Verwaltungsaufwand verbunden. Näheres zu Indexen und den zur Realisierung verwendeten Datenstrukturen in der Vorlesung Datenbanken oder in der begleitenden Literatur (siehe Blatt der ersten Woche). Das Anlegen eines Index geht mit dem CREATE INDEX-Statement, das Löschen entsprechend über DROP INDEX. Man benötigt dazu mindestens das INDEX- oder das CONTROL-Recht für die Tabelle, sowie das CREATEIN-Recht im angegebenen Schema. Der Benutzer, der einen Index anlegt, erhält auf diesem das CONTROL- Recht. Über das Schlüsselwort UNIQUE kann man bei der Erstellung eines Index angeben, dass keine Tupel in allen Werten der angegebenen Attribute übereinstimmen dürfen. Sollten zum Zeitpunkt der Indexgenerierung Tupel in der Tabelle dagegen verstoßen, so wird eine Fehlermeldung ausgegeben und der Index nicht angelegt. Es ist nicht möglich, zwei gleiche Indexe anzulegen. Dabei darf ein Index 16 Attribute umfassen und die Attribute dürfen zusammen nicht länger als 1024 Bytes sein. Die Ordnung ASC bzw. DESC gibt an, ob die Indexeinträge in aufsteigender bzw. absteigender Reihenfolge angelegt werden. Nur wenn UNIQUE angegeben wurde, können über die INCLUDE-Klausel weitere Attribute in den Index aufgenommen werden, für die aber keine Schlüsselbedingung gelten soll. Beispiel: CREATE INDEX adressen ON anwender (adresse) Indexe werden nicht explizit aufgerufen, sondern vom Datenbank- Managementsystem implizit bei der Bearbeitung von Anfragen herangezogen. S. 268 Übersicht über die neuen Befehle drop trigger name... create function name... drop function name create trigger name... drop trigger name... create index name on table... drop index name... describe indexes for table name lösche den Trigger name erstelle eine neue Funktion name lösche die Funktion name erstelle einen neuen Trigger name lösche den Trigger name erzeuge einen neuen Index auf einer Tabelle lösche den Trigger name zeige die Indexe auf der Tabelle name an Seite 13 von 16

Aufgaben Vorbereitung (Hausaufgaben) V0: SQL Programming Language Dieses Aufgabenblatt kann die SqlPl nur sehr oberflächlich einführen. Benutzt daher das Online-Handbuch, um Euch auch anhand von Beispielen besser mit dieser einfachen Programmiersprache vertraut zu machen. Macht Euch mit Hilfe der angegebenen Handbuchabschnitte, bzw. der Online- Dokumentation oder anderer Literatur mit der Syntax des WITH...SELECT- Statements vertraut. V1: WITH... SELECT-Statement Was sind andere Nutzen für einen in der WITH-Klausel definierten Tabellenausdruck außer der Verwendung in rekursiven Anfragen? V2: Verwendung von Triggern (a) Überlegt Euch mindestens zwei weitere Beispiele in Eurer eigenen Datenbank, wo Ihr Trigger sinnvoll einsetzen könntet. (b) Vergleicht Trigger mit Constraints. Werden beide für dieselbe Zwecke verwendet, oder gibt es Unterschiede? Wann ist es sinnvoller, mit Triggern statt mit Constraints zu arbeiten? V3: Verwendung von Funktionen Welche Unterschiede seht Ihr in der Verwendung von Triggern bzw. benutzerdefinierten Funktionen? Wann sind Trigger sinnvoller, wann eigene Funktionen? Gibt es in Eurer eigenen Datenbank sinnvolle Anwendungsmöglichkeiten für skalare oder für tabellenwertige Funktionen? Seite 14 von 16

Präsenz P1: Index anlegen Erstellt zumindest einen sinnvollen Index aus zwei oder mehr Attributen auf Eurer Datenbank. P2: Trigger Aus Performanzgründen kann es sinnvoll sein, bestimmte häufige Anfragen nicht ständig neu an die Datenbank zu stellen, sondern die Ergebnisse in einer Tabelle vorzuhalten. Falls die Berechnung der Taghäufigkeiten pro Werk etwa sehr lange dauert, ist es ggf. besser diese bei Änderungen an der Datenbasis direkt mitzuzählen. Legt eine Tabelle TagsWerk mit Spalten für WerkID, TagID und TagAnzahl an. Erstellt dann einen Trigger für Eure Datenbank, der bei Hinzufügung eines Tags für ein zum Werk gehöriges Buch den Counter für den Tag bei dem entsprechenden Werk erhöht. Wenn die Zeit bleibt, schreibt zusätzliche Update- und Delete-Trigger, die entsprechend die Anzahl des Tags bei einem Löschen eines Tagtupels verringern, bzw. die Anzahl des Tags bei einer Änderung des Tagnamens entsprechend anpasst. P3: Tabellenwertige Funktion Schreibt eine tabellenwertige Funktion WerkExemplar, die eine WerkID als Parameter erhält. Diese Funktion sollte eine Tabelle mit zwei Spalten BibID und BesitzerID zurückliefern. Dabei sollen die Tupel der Tabelle alle Bibliotheksobjekte aufzählen, die zu diesem Werk gehören (dieses enthalten) sowie deren Besitzer. Wer mag, kann die Lösung dahingehend erweitern, dass zusätzlich noch eine dritte Spalte mit der Information ausgegeben wird, ob der Besitzer dieses Bibliotheksobjekt bereits getaggt hat (es bleibt Euch überlassen, wie Ihr diesen Wahrheitswert ausdrückt). Seite 15 von 16

P4: Rekursive Anfrage In der Beispieldatenbank bibsampl existieren unter anderen die beiden Tabellen category und incat: Es gibt 534 Kategorien, die teilweise noch weitere Unterkategorien besitzen. Jede Kategorie kann jedoch nur zu höchstens einer Oberkategorie gehören. Der Einfachheit halber wurden in der Beispieldatenbank Werke statt Büchern kategorisiert. Dabei kann jedes Werk mehreren Kategorien zugeordnet sein. Es ist immer nur die spezifischste Kategorie angegeben, ein Werk in einer Unterkategorie gehört jedoch automatisch auch zu deren Oberkategorie. Beispielsweise ist das Werk 10th Kingdom, the aus dem Jahre 1999 in der Kategorie Fiction > Fantasy > Contemporary (Nummer 473) eingeordnet. Die Kategorie mit der Nummer 473 ist jedoch unter der Kategorie Fiction > Fantasy (Nummer 47), und diese wiederum unter der Kategorie Fiction angesiedelt. Damit gehört das Werk 10th Kingdom, the automatisch auch zu den Fantasywerken und ist Fiction, obwohl es keine explizites Tupeln dafür gibt. Aufgabe (eine wählen): Schreibt eine rekursive Anfrage auf der Beispieldatenbank, die zu dem Werk Heartlight von 1998 alle Kategorien zurückliefert (inklusive der Oberkategorien). Schreibt eine rekursive Anfrage auf der Beispieldatenbank, die ausgehend von der Oberkategorie mit der ID 0 zu allen Kategorien den kompletten Kategorienamenspfad statt nur den letzten Bestandteil ausgibt. Zur Kategorie 473 sollte die Ausgabe also beispielsweise Fiction > Fantasy > Contemporary statt Contemporary lauten. Zum Schluss... stoppt bitte Eure Datenbank-Manager-Instanz auf salz, loggt Euch von salz und vom lokalen Rechner aus, aber schaltet den Rechner nicht ab. Seite 16 von 16