10. Anwendungsprogrammierung ■ Client-Server-Architektur ■ Anbindung von Programmiersprachen ■ Call-Level-Schnittstellen: SQL/CLI, JDBC ■ Einbettung: Embedded SQL, SQLJ ■ Gespeicherte Prozeduren ■ Prozedurale Erweiterungen: SQL/PSM, PL/SQL VL Datenbanken I – 10–1 Client-Server-Architektur ■ typische Architektur von DB-Anwendungen, da zentrale Verwaltung durch DBMS notwendig ■ Prinzip: Client nimmt Dienste eines Servers in Anspruch ■ erfordert ◆ Kenntnis über angebotene Dienste ◆ Protokoll zur Regelung der Interaktion VL Datenbanken I – 10–2 Client-Server-Modell Client (Dienstnehmer) Server (Diensterbringer) 1.Anforderung 2.Bearbeitung 3.Antwort VL Datenbanken I – 10–3 Funktionsgruppen in DB-Anwendungen ■ Präsentation und Benutzerinteraktion ■ Anwendungslogik ■ Datenmanagementfunktionalität VL Datenbanken I – 10–4 2-Schichten-Architektur Benutzerschnittstelle Client Anwendungslogik DB-Schnittstelle DBMS-Protokoll DB-Server VL Datenbanken I – 10–5 3-Schichten-Architektur Benutzerschnittstelle Client CORBA, RMI, ... Anwendungslogik DB-Schnittstelle Applikationsserver DBMS-Protokoll DB-Server VL Datenbanken I – 10–6 Programmiersprachenanbindung Kopplungsarten: ■ prozedurale oder CALL-Schnittstellen (call level interface) ■ Einbettung einer DB-Sprache in Programmiersprachen ◆ statische Einbettung: Vorübersetzer-Prinzip ; SQL-Anweisungen zur Übersetzungszeit festgelegt ◆ dynamische Einbettung: ; Konstruktion von SQL-Anweisungen zur Laufzeit ■ Spracherweiterungen und neue Sprachentwicklungen VL Datenbanken I – 10–7 Cursor-Konzept Anwendungsprogramm PASCAL Cursor Datenbank SQL Relation VL Datenbanken I – 10–8 Cursor in SQL Cursor-Deklaration: declare AktBuch cursor for select ISBN, Titel, Verlagsname from Bücher where Verlagsname = ’Thomson’; Cursor-Deklaration mit Änderungsmöglichkeit: declare AktBuch cursor for select ISBN, Titel, Verlagsname from Bücher for update of ISBN, Titel; VL Datenbanken I – 10–9 Cursor in SQL2 declare CursorName [insensitive] [scroll] cursor for ... ■ next: Gehe weiter zum nächsten Tupel ■ prior: Gehe zum vorherigen Tupel ■ first bzw. last: Gehe zum ersten bzw. letzten Tupel ■ absolute n from: Gehe zum n-ten Tupel des Cursors (negative Werte werden relativ zum letzten Tupel rückwärts gewertet — absolute -1 ist also äquivalent zu last) ■ relative n from: Gehe zum n-ten Tupel relativ zur aktuellen Cursor-Position VL Datenbanken I – 10–10 SQL/CLI: Der Standard ■ Call-Level-Interface: Bibliothek von Prozeduren/Funktionen zur ◆ Kommunikation mit dem DBMS ◆ Definition und Ausführung von Anfragen ◆ Verarbeitung von Ergebnissen ■ SQL/CLI: ISO-Standard für API ■ Programmiersprachen: C/C++, Ada, Fortran, Pascal, . . . VL Datenbanken I – 10–11 CLI: Handles ■ Handle: Verweis auf globale Datenstruktur zur Kommunikation mit DBMS ■ C-Datentyp: SQLHANDLE ■ erforden explizite Allokation (SQLAllocHandle) ■ Arten: ◆ Environment Handles: Verwaltung des globalen Zustandes der Applikation ◆ Connection Handles: Verwaltung von Verbindungsdaten ◆ Statement Handles: Informationen zu einer SQL-Anweisung ◆ Description Handles: Daten zu Ergebnisspalten bzw. Paramtern VL Datenbanken I – 10–12 CLI: Aufbau einer DB-Verbindung 1. Handles allokieren SQLHANDLE henv; /* Environment Handle */ SQLHANDLE hdbc; /* Connection Handle */ SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); if (SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc) != SQL_SUCCESS) /* Fehlerbehandlung */ 2. Verbindung herstellen SQLCHAR *server = "shop_db", *uid = "scott", *pwd = "tiger"; SQLConnect (hdbc, server, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); VL Datenbanken I – 10–13 CLI: Anfrageausführung SQLHANDLE hstmt; SQLCHAR *select = "select KNr, Name, Ort from Kunde"; SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt); SQLExecDirect (hstmt, select, SQL_NTS); VL Datenbanken I – 10–14 CLI: Ergebnisverarbeitung 1. Bindung an Variablen herstellen SQLINTEGER knr; SQLCHAR kname[31], kort[51]; SQLBindCol (hstmt, 1, (SQLPOINTER) &knr, SQLBindCol (hstmt, 2, kname, 31, NULL); SQLBindCol (hstmt, 3, kort, 51, NULL); SQL_C_LONG, 0, NULL); SQL_C_CHAR, SQL_C_CHAR, 2. Ergebnisse auslesen while (SQLFetch (hstmt) == SQL_SUCCESS) printf ("Kunde = %ld, %s, %s\n", knr, kname, kort); VL Datenbanken I – 10–15 CLI: Transaktionssteuerung ■ Transaktion erfolgreich beenden SQLEndTrans (SQL_HANDLE_DBC, hdbc, SQL_COMMIT); ■ Transaktion abbrechen SQLEndTrans (SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK); VL Datenbanken I – 10–16 ODBC ■ SQL/CLI-konforme Implementierung für Microsoft Windows ■ Zugriff auf verschiedene Datenbanksysteme über systemspezifische Treiber möglich ■ dynamisches Laden von Treibern (implementiert als DLL) ■ Registrierung von Datenquellen mit Name, System, Treiber, Verbindungsinformation VL Datenbanken I – 10–17 JDBC: Überblick ■ Datenbankzugriffsschnittstelle für Java ■ abstrakte, datenbankneutrale Schnittstelle ■ vergleichbar mit ODBC ■ Low-Level-API: direkte Nutzung von SQL ■ Java-Package java.sql ◆ DriverManager: Einstiegspunkt, Laden von Treibern ◆ Connection: Datenbankverbindung ◆ Statement: Ausführung von Anweisungen über eine Verbindung ◆ ResultSet: verwaltet Ergebnisse einer Anfrage, Zugriff auf einzelne Spalten VL Datenbanken I – 10–18 JDBC: Ablauf 1. Aufbau einer Verbindung zur Datenbank ■ Angabe der Verbindungsinformationen ■ Auswahl und Laden des Treibers 2. Senden einer SQL-Anweisung ■ Definition der Anweisung ■ Belegung von Parametern 3. Verarbeiten der Anfrageergebnisse ■ Navigation über Ergebnisrelation ■ Zugriff auf Spalten VL Datenbanken I – 10–19 JDBC: Verbindungsaufbau 1. Treiber laden Class.forName ("com.company.DBDriver"); 2. Verbindung herstellen Connection con; String url = "jdbc:subprotocol:datasource"; con = DriverManager.getConnection (url, "scott", "tiger"); JDBC-URL spezifiziert ■ Datenquelle/Datenbank ■ Verbindungsmechanismus (Protokoll, Server-Host und Port) VL Datenbanken I – 10–20 JDBC: Anfrageausführung 1. Anweisungsobjekt (Statement) erzeugen Statement stmt = con.createStatement (); 2. Anweisung ausführen String query = "SELECT titel, preis FROM buch"; ResultSet rset = stmt.executeQuery (query); Klasse java.sql.Statement ■ Ausführung von Anfragen (SELECT) mit executeQuery ■ Ausführung von Änderungsanweisungen (DELETE, INSERT, UPDATE) mit executeUpdate VL Datenbanken I – 10–21 JDBC: Ergebnisverarbeitung 1. Navigation über Ergebnismenge (Cursor-Prinzip) while (rset.next ()) { // Verarbeitung der einzelnen Tupel ... } 2. Zugriff auf Spaltenwerte über getType-Methoden ■ über Spaltenindex String titel = rset.getString (1); ■ über Spaltenname String titel = rset.getString ("titel"); VL Datenbanken I – 10–22 JDBC: Fehlerbehandlung ■ Fehlerbehandlung mittels Exception-Mechanismus ■ SQLException für alle SQL- und DBMS-Fehler try { // Aufruf von JDBC-Methoden ... } catch (SQLException exc) { System.out.println (SSQLException: "+ exc.getMessage ()); } VL Datenbanken I – 10–23 JDBC: Änderungsoperationen ■ DDL- und DML-Operationen mittels executeUpdate ■ liefert Anzahl der betroffenen Zeilen (für DML-Operationen) Statement stmt = con.createStatement (); int rows = stmt.executeUpdate ( " UPDATE buch SET bestand = bestand-1"+ " WHERE isbn = ’12345’ "); VL Datenbanken I – 10–24 JDBC: Transaktionssteuerung ■ Methoden von Connection ◆ commit () ◆ rollback () Auto-Commit-Modus ◆ implizites Commit nach jeder Anweisung ◆ Transaktion besteht nur aus einer Anweisung ◆ Umschalten mittels setAutoCommit (boolean) VL Datenbanken I – 10–25 Statische Einbettung: Embedded SQL exec sql declare AktBuch cursor for select ISBN, Titel, Verlagsname from Bücher for update of ISBN, Titel; Öffnen und Schließen einer Datenbank exec sql connect UniBeispiel; VL Datenbanken I – 10–26 Deklarationen ■ Deklaration benutzter Datenbankrelationen exec sql declare Buch table ( ISBN char(10) not null, Titel char(120) not null, Verlagsname char(30) not null); ■ Deklaration gemeinsamer Variablen exec sql begin declare section; BuchISBN char(10); NeuerPreis real; exec sql end declare section; VL Datenbanken I – 10–27 Datentransfer exec sql update Buch_Versionen set Preis = :NeuerPreis where ISBN = :BuchISDN ; exec sql insert into Buch_Versionen values (:NeuISBN, :NeuAuflage, 1995, :Seiten, :Preis); exec sql select ISBN, Auflage, Jahr, Preis into :ISBN, :Auflage, :Jahr, :Preis from Buch_Versionen where ISBN = :SuchISBN and Auflage = 1; VL Datenbanken I – 10–28 Datentransfer (II) Indikator-Variablen zum Test auf null-Werte: exec sql select :ISBN, Auflage, Jahr, Preis into :ISBN, :Auflage, :Jahr, :Preis:PreisInd from Buch_Versionen where ISBN = :SuchISBN and Auflage = :SuchAuflage; VL Datenbanken I – 10–29 Einsatz der Cursor-Technik exec sql open AktBuch; exec sql fetch AktBuch into :ISBN, :Titel, :Verlagsname; exec sql close AktBuch; exec sql delete from Bücher where current of AktBuch; VL Datenbanken I – 10–30 Fehler- und Ausnahmebehandlung SQL Communication Area exec sql include sqlca; ‘whenever’-Anweisung exec sql whenever <Bedingung> <Aktion>; ■ not found: Kein Tupel wurde gefunden, definiert etwa als sqlcode = 100. ■ sqlwarning: Warnung, entspricht etwa sqlcode > 0 ∧ sqlcode 6= 100. ■ sqlerror: Fehler, also sqlcode < 0. VL Datenbanken I – 10–31 Transaktionssteuerung exec sql commit work; exec sql rollback work; VL Datenbanken I – 10–32 Dynamische Einbettung: Dynamic SQL exec sql begin declare section; AnfrageString char(256) varying; exec sql end declare section; exec sql declare AnfrageObjekt statement; AnfrageString := ’DELETE FROM Vorlesungen WHERE SWS < 2’; ... exec sql prepare AnfrageObjekt from :AnfrageString; exec sql execute AnfrageObjekt; „Anfragen als Zeichenketten“ VL Datenbanken I – 10–33 Dynamische Einbettung: Dynamic SQL ... AnfrageString := ’DELETE FROM Buch_Versionen ’ + ’WHERE ISBN = ? AND Auflage = ?’ ; exec sql prepare AnfrageObjekt from :AnfrageString; exec sql execute AnfrageObjekt using :LöschISBN, :LöschAuflage; Wertübergabe an Anfragen VL Datenbanken I – 10–34 SQLJ: Embedded SQL für Java ■ Einbettung von SQL-Anweisungen in Java-Quelltext ■ Vorübersetzung des erweiterten Quelltextes in echten Java-Code durch Translator sqlj ■ Überprüfung der SQL-Anweisungen ◆ korrekte Syntax ◆ ◆ ■ Übereinstimmung der Anweisungen mit DB-Schema Typkompatibilität der für Datenaustausch genutzten Variablen Nutzung von JDBC-Treibern VL Datenbanken I – 10–35 SQLJ-Anweisungen ■ Kennzeichnung durch #sql Deklarationen ■ Klassendefinitionen für Iteratoren ■ SQL-Anweisungen: Anfragen, DML- und DDL-Anweisungen #sql { SQL-Operation }; ■ Beispiel: #sql { INSERT INTO buch VALUES ("Datenbanken", 59.00, "123456", "MITP") }; VL Datenbanken I – 10–36 Host-Variablen ■ Variablen einer Host-Sprache (hier Java), die in SQL-Anweisungen auftreten können ■ Verwendung: Austausch von Daten zwischen Host-Sprache und SQL ■ Kennzeichnung durch ":variable" ■ Beispiel: String titel, isbn = "123456"; #sql { SELECT titel INTO :titel FROM buch WHERE isbn = :isbn }; VL Datenbanken I – 10–37 Iteratoren Implementierung des Cursor-Konzeptes 1. Deklaration des Iterators #sql public iterator BookIter (String titel, double preis); 2. Definition des Iteratorobjektes BookIter iter; 3. Ausführung der Anweisung #sql iter = { SELECT titel, preis FROM buch }; 4. Navigation while (iter.next ()) { System.out.println (iter.titel () + " "+ iter.preis ()); } VL Datenbanken I – 10–38 Gespeicherte Prozeduren ■ Probleme von CLI und Embedded SQL: ◆ ständiger Wechsel der Ausführungskontrolle zwischen Anwendung und DBS ◆ keine anweisungsübergreifende Optimierung notwendig ■ Ausweg: gespeicherte Prozeduren ◆ im Datenbank-Server verwaltete und auch dort ausgeführte Software-Module in Form von Prozeduren bzw. Funktionen ◆ Aufruf aus Anwendungen und Anfragen heraus VL Datenbanken I – 10–39 Vorteile Gespeicherter Prozeduren ■ Strukturierungsmittel für größere Anwendungen ■ Prozeduren nur vom DBMS abhängig und nicht von externen Programmiersprachen oder Betriebssystemumgebungen ■ Optimierung der Prozeduren ■ Ausführung der Prozeduren unter Kontrolle des DBMS ■ zentrale Kontrolle der Prozeduren: redundanzfreie Darstellung relevanter Aspekte der Anwendungsfunktionalität ■ Rechtevergabe für Prozeduren ■ in der Integritätssicherung: Aktionsteil von Triggern VL Datenbanken I – 10–40 SQL/PSM: Der Standard ■ SQL-Standard für prozedurale Erweiterungen ■ PSM: Persistent Stored Modules ◆ gespeicherte Module aus Prozeduren und Funktionen ◆ Einzelroutinen ◆ Einbindung externer Routinen (implementiert in C, Java, . . . ) ◆ syntaktische Konstrukte für Schleifen, Bedingungen etc. VL Datenbanken I – 10–41 SQL/PSM: Funktionen ■ Funktionsdefinition create function dm_in_euro (float v) returns float begin return (v / 1.95583); end; ■ Aufruf innerhalb einer Anfrage select Bezeichnung, dm_in_euro (Preis) from Produkt where dm_in_euro (Preis) < 100 ■ Nutzung außerhalb von Anfragen set euro_preis = dm_in_euro (79.00); VL Datenbanken I – 10–42 SQL/PSM: Prozeduren ■ Prozedurdefinition create procedure rechnungsbetrag ( in int nr, out float summe) begin select sum(p.Preis ∗ bp.Anzahl) into summe from Bestellposten bp, Produkt p where bp.BestNr = nr and bp.ProdId = p.ProdId; end; ■ Nutzung über call-Anweisung declare preis float; call rechnungsbetrag (42, preis); VL Datenbanken I – 10–43 SQL/PSM: Zugriffscharakteristik ■ Eigenschaften von Prozeduren, die Anfrageausführung und -optimierung beeinflussen ◆ deterministic: Routine liefert für gleiche Parameter gleiche Ergebnisse ◆ no sql: Routine enthält keine SQL-Anweisungen ◆ contains sql:Routine enthält SQL-Anweisungen (Standard für SQL-Routinen) ◆ reads sql data: Routine führt SQL-Anfragen (select-Anweisungen) aus ◆ modifies sql data: Routine, die DML-Anweisungen (insert, update, delete) enthält VL Datenbanken I – 10–44 SQL/PSM: Ablaufkontrolle ■ Variablendeklaration declare name varchar(50); ■ Zuweisung set var = 42; ■ Bedingte Verzweigungen if <Bedingung> then <Anweisungen> [ else <Anweisungen> ] end if; ■ Schleifen loop <Anweisungen> end loop while <Bedingung> do <Anweisungen> end while repeat <Anweisungen> until <Bedingung> end repeat VL Datenbanken I – 10–45 SQL/PSM: Ausnahmebehandlung ■ Auslösen einer Ausnahme (Condition) signal <ConditionName>; ■ Deklarieren von Ausnahmen declare yyy condition; ■ Ausnahmebehandlung begin declare exit handler for <ConditionName> begin <Ausnahmebehandlung>; end <Anweisungen>; end VL Datenbanken I – 10–46 PL/SQL von Oracle ■ prozedurale SQL-Erweiterung für Oracle ■ Merkmale ◆ erweitertes Typsystem ◆ Package-Konzept Deklarationen declare Heute date; type PersonRecordType is record ( PersonName varchar (50), GebDatum date); Mitarbeiter PersonRecordType; VL Datenbanken I – 10–47 PL/SQL: Cursor cursor AktBuch is select ISBN, Titel, Verlagsname from Bücher; Zugriff auf Typinformation AktPersName Mitarbeiter.PersonName%type; BuchTupel AktBuch%rowtype; VL Datenbanken I – 10–48 Operationale Konstrukte if <Bedingung> then <PL/SQL-Anweisungen> [ else <PL/SQL-Anweisungen> ] end if; for <IndexVariable> in <EndlicherBereich> loop <PL/SQL-Anweisungen>; end loop; while <Bedingung> loop <PL/SQL-Anweisungen>; end loop; VL Datenbanken I – 10–49 Iteration über Tabellen for BuchRec in AktBuch loop ... end loop; entspricht declare BuchRec AktBuch%rowtype; begin loop fetch AktBuch into BuchRec; exit when AktBuch%notfound; ... end loop; VL Datenbanken I – 10–50 Fehlerbehandlung when Ausnahme then ProgrammStück; VL Datenbanken I – 10–51 PL/SQL: Gespeicherte Prozeduren create function FunktionsName ( Param1 ParamTyp1, ..., ParamN ParamTypN ) return ErgebnisTyp is /* PL/SQL - Block mit return-Anweisung */ create procedure ProzedurName ( Param1 in ParamTyp1, ( Param2 out ParamTyp2, ( Param3 in out ParamTyp3, ... ) is /* PL/SQL - Block mit Zuweisungen an out-Parameter */ VL Datenbanken I – 10–52 Weitere Prozedurale SQL-Erweiterungen ■ IBM DB2: SQL/PSM ■ Informix: SPL ■ Sybase, Microsoft SQL Server: Transact-SQL ■ externe Routinen: implementiert in C, Java, . . . VL Datenbanken I – 10–53