Kapitel 9: Datenbankapplikationen 1 Datenbankapplikationen ODBC MS Visio MS Access Embedded SQL JDBC Application JDBC Applet Java Servlet Java Server Pages Cold Fusion PHP DQ im Client DQ im Client DQ im Client DB-Server-Protokoll DQ im Client DQ im Client DB-Server-Protokoll DB-Server-Protokoll DQ im DB-Server DB-Server-Protokoll 2 ODBC Open Data base connectivity Anwendungsprogramm ODBC-Datenquelle Informix Microsoft Client Client Oracle Client 3 Demo Systemsteuerung voraussetzen MS Visio Studenten PK PK,FK2 PK,FK1 hoeren MatrNr PK,FK1 PK,FK2 Name Semester GebDatum pruefen PK,FK2 PK,FK3 MatrNr VorlNr FK1 PersNr Note MatrNr VorlNr Vorgaenger Nachfolger Vorlesungen PK VorlNr FK1 Titel SWS gelesenVon Professoren PK PersNr Name Rang Raum Gebdatum U1 Assistenten PK FK1 PersNr Name Fachgebiet Boss GebDatum Demo Visio 4 MS Access Stand-alone Datenbanksystem Frontend per ODBC für relationale Datenbank •Schemadesign •Beziehungen •Queries •Beziehungen •Reports •Formulare Demo Access 5 Zugriff per Programmiersprachen • • • • • Embedded SQL JDBC Application JDBC Applet Java Servlet Java Server Pages 6 Embedded SQL Host-Programm: hallo.pc SQL Include Files Präprozessor Quell-Programm: hallo.c C-Compiler Objekt-Programm: C Include Files hallo.o C-Linker Ausführbares Programm: Runtime Library hallo.exe 7 Hostvariable int char char int char persnr; name[20]; rang[3]; raum; gebdatum[17]; // // // // // Personalnummer Name Rang Raum Geburtsdatum short raum_ind; // Raum-Indikator Innerhalb von SQL-Statements: Doppelpunkt (:) voranstellen ! 8 Select EXEC SQL SELECT persnr, raum INTO :persnr, :raum INDICATOR :raum_ind FROM Professoren WHERE PersNr = 2125; if (raum_ind == -1) printf("Personalnummer %d ohne Raumangabe \n”,persnr); 9 Cursor deklarieren EXEC SQL DECLARE C1 CURSOR FOR SELECT PersNr, Name, Rang, Raum, Gebdatum FROM Professoren WHERE Rang = :eingaberang; 10 Cursor füllen + transferieren EXEC SQL OPEN C1; EXEC SQL FETCH C1 INTO :persnr, :name, :rang, :raum INDICATOR :raum_ind, :gebdatum; 11 Inhalt abarbeiten while (SQLCODE == 0) printf("%d %s %s", persnr, name, rang); if(raum_ind == -1) printf(" ???"); else printf("%4d", raum); printf(" %s\n", gebdatum); EXEC SQL FETCH C1 INTO :persnr, :name, :rang, :raum:raum_ind, :gebdatum; } EXEC SQL CLOSE C1; 12 Beispiel.sqc, Teil 1 void ErrorHandler (void); #include <stddef.h> #include <stdio.h> int main ( int argc, char** argv, char** envp) { EXEC SQL BEGIN DECLARE SECTION; char serverDatenbank[] = "arnold.uni"; char loginPasswort[] = "erika.mustermann"; int persnr; char name[20]; char rang[3]; int raum; char gebdatum[17]; short raum_ind; char eingaberang[3]; EXEC SQL END DECLARE SECTION; // Standardheader // Standardheader // // // // // // // // // // // Deklarationen-Start Server + DB User + Passwort Personalnummer Name Rang Raum Geburtsdatum Raum-Indikator Eingabe vom User Deklarationen-Ende 13 Beispiel.sqc, Teil 2 EXEC SQL WHENEVER SQLERROR CALL ErrorHandler(); // Fehlermarke EXEC SQL CONNECT TO :serverDatenbank // Verbindung aufbauen USER :loginPasswort; printf("Bitte Rang eingeben: "); // gewuenschten Rang scanf("%s", eingaberang); // vom user holen printf("Mit Rang %s gespeichert:\n", eingaberang); EXEC SQL DECLARE C1 CURSOR FOR SELECT PersNr, Name, Rang, Raum, Gebdatum FROM Professoren WHERE Rang = :eingaberang; // Cursor vereinbaren // SQL-Statement EXEC SQL OPEN C1; EXEC SQL FETCH C1 INTO :persnr, :name, :rang, :raum INDICATOR :raum_ind, :gebdatum; // Cursor oeffnen // Versuche eine Zeile // zu lesen 14 Beispiel.sqc, Teil 3 while (SQLCODE == 0) { printf("%d %s %s", persnr, name, rang); if(raum_ind == -1) printf(" ???"); else printf("%4d", raum); printf(" %s\n", gebdatum); // SOLANGE erfolgreich // Tupel ausgeben // FALLS keine Raumnr // Platzhalter drucken // SONST Raumnr // letztes Attribut EXEC SQL FETCH C1 INTO :persnr, :name, :rang, // naechste Zeile :raum:raum_ind, :gebdatum; } EXEC SQL CLOSE C1; EXEC SQL DISCONNECT ALL; return (0); } // Cursor schliessen // Verbindung beenden 15 Beispiel.sqc, Fehlerroutine void ErrorHandler (void) { printf("In Error Handler:\n"); printf(" SQL Code = %li\n", SQLCODE); printf(" SQL Server Message %li: '%Fs'\n", SQLERRD1, SQLERRMC); } 16 beispiel.exe Demo: beispiel.exe 17 JDBC Java-Programm mit Klassen aus java.sql läuft im Clienten • • Application Applet • • • Treiber laden und Verbindung herstellen SQL-Statement ausführen Ergebnis verarbeiten 18 JDBC Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection con = DriverManager.getConnection ("jdbc:odbc:dbs","erika","mustermann"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery ("select * persnr, name from professoren"); while (rs.next()) { int x = rs.getInt("persnr"); String s = rs.getString("name"); System.out.println("Professor "+s+" hat Nr. "+x); } 19 JDBC Application $ Javac ShowJdbc.java $ java ShowJdbc Demo: Java ShowJdbc 20 JDBC Applet public class JdbcApplet extends Applet { BorderLayout = new Border Layout(); ... <HTML> <HEAD> <TITLE>JDBC Test-Applet</TITLE> </HEAD> <BODY bgColor=Silver> <CENTER> <H2> Demo-Applet für JDBC-Datenbankzugriff</H2> <APPLET codebase =. code =JdbcApplet width =700 height =400> </APPLET> </CENTER> </BODY> </HTML> Demo: JdbcApplet 21 Java Servlet Java-Programm mit Klassen aus javax.servlet.* läuft auf Server • • • • HTML-Form ausfüllen Argumente an Servlet schicken Servlet beantwortet Query mit JDBC Ergebnis wird als HTML zurückgeschickt 22 VorVrz.java ... String query = "select v.vorlnr, v.titel, v.sws " + "from vorlesungen v, professoren p " + "where v.gelesenvon = p.persnr and p.name ='" + request.getParameter("professor_name") + "'"; rs = stmt.executeQuery(query); out.println("<HTML>"); out.println("<HEAD><TITLE>Java Servlet</TITLE></HEAD>"); out.println("<BODY>"); out.println("<H1>Vorlesungen von Prof. " + request.getParameter("professor_name") +": </H1>"); out.println("<UL>"); while (rs.next()) out.println("<LI>" + rs.getInt("VorlNr") + ": " + rs.getString("Titel") + " (mit " + rs.getInt("SWS") + " SWS)" + "</LI>"); out.println("</UL>"); out.println("<BODY></HTML>"); ... 23 Aufruf des Servlets public class VrlVrz extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... <HTML> <HEAD> <TITLE>Vorlesungsverzeichnis mit Java Servlet</TITLE> </HEAD> <BODY> <FORM METHOD="GET" ACTION="VrlVrz"> Bitte geben Sie den Namen eines Professors ein: <P><INPUT NAME="professor_name" SIZE="40"><P> <INPUT TYPE="submit" VALUE="Vorlesungen ermitteln"> </FORM> </BODY> </HTML> Demo: Servlet 24 Java Server Pages Trennung von Form und Funktionalität: • • Java-Klasse HTML-Seite mit Aufruf von Java-Methoden wird übersetzt zu Servlet 25 VorlesungenBean.java (Teil 1) package dbs; import java.sql.*; public class VorlesungenBean { Connection con = null; String con_err = null; String profname = null; public VorlesungenBean() { try { Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); con = DriverManager.getConnection( "jdbc:microsoft:sqlserver://arnold.informatik.uni-osnabrueck.de:1433", "erika","mustermann"); } catch(Exception e) { con_err = e.toString(); } } public void setProfname(String name) { profname = name; } public String getProfname() { return profname; } 26 VorlesungenBean.java (Teil 2) public String generiereVorlListe(){ Statement stmt = null; ResultSet rs = null; if (con==null) return ("Probleme mit der Datenbank: "+con_err + "<BR>"); StringBuffer result = new StringBuffer(); try{ stmt = con.createStatement(); String query = "select v.vorlnr, v.titel, v.sws from vorlesungen v, professoren p "+ "where v.gelesenvon = p.persnr and p.name ='" + profname + "'"; rs = stmt.executeQuery(query); result.append("<UL>"); while (rs.next()) result.append("<LI>"+rs.getInt("VorlNr")+": "+rs.getString("Titel")+ " (mit " + rs.getInt("SWS") + " SWS)" + "</LI>"); result.append("</UL>"); } catch(SQLException e) { result = new StringBuffer("Bei der Abfrage fuer " + profname + " trat ein Fehler auf: " + e.getMessage() + "</BR>"); } return result.toString(); } 27 VorlesungenBean.java (Teil 3) public void finalize () { try {if (con != null ) con.close();} catch (SQLException ignorieren) {} } } 28 vorlesungen.jsp <%@ page import = "dbs.VorlesungenBean" %> <jsp:useBean id="prg" class="dbs.VorlesungenBean" scope="request"/> <jsp:setProperty name="prg" property="*"/> <html> <% if (prg.getProfname() == null) { %> <head><title>Professoren-Namen erfassen</title></head> <body bgcolor="DDDDDD"> <FORM METHOD="GET"> Bitte geben Sie den Namen eines Professors ein:<P> <INPUT TYPE=TEXT NAME=profname><P> <INPUT TYPE=SUBMIT VALUE="Vorlesungen ermitteln!"> </FORM> </body> <% } else { %> <head><title>Vorlesungen ausgeben</title></head> <body bgcolor="DDDDDD"> Die Vorlesungen von <%= prg.getProfname() %> lauten: <P> <%= prg.generiereVorlListe() %> </body> <% } %> </html> 29 Datenbankapplikationen MS Access Embedded SQL printf("Professor %s", profname); JDBC Application System.out.println("Prof." + rs.getString("name"); JDBC Applet outputArea.append( rs.getString("name") ); Java Servlet out.println("<P>" + rs.getString("name") ); Java Server Pages <P>Vorlesung <%= prg.getProfname() %> Cold Fusion <CFOUTPUT QUERY="q1">#profname#</CFOUTPUT> PHP echo "<P>$tupel[0]"; 30 Cold Fusion Web-Browser Web-Server Application Server Datenbankserver 31 studliste.cfm <CFQUERY NAME = USERNAME = PASSWORD = DATASOURCE = DBTYPE = SELECT matrnr, name </CFQUERY> "Studentenliste" "erika" "mustermann" "dbs" "ODBC"> from studenten <HTML> <HEAD> <TITLE> Studentenliste </TITLE> </HEAD> <BODY> <H2> Studentenliste (unformatiert)</H2> <CFOUTPUT QUERY="Studentenliste"> #name# #matrnr# <BR> </CFOUTPUT> </BODY> </HTML> Demo: Coldfusion 32 PHP • • • • Personal Home Page Server-basierte Scriptsprache Integriert in HTML-Seiten Grafik-Library GD 33 frage.html <HTML> <HEAD> <TITLE>Frage</TITLE> </HEAD> <BODY> <FORM METHOD="POST" ACTION="antwort.php"> Bitte geben Sie Ihre SQL-Query ein: <P><INPUT NAME="frage" SIZE="70"> <P> <INPUT TYPE="submit" VALUE="Query absetzen"> </FORM> </BODY> </HTML> 34 antwort.php (Teil 1) <HTML> <HEAD> <TITLE>Antwort auf Datenbank Query</TITLE> </HEAD> <BODY BGCOLOR="DDDDDD"> <?php $con=mssql_connect("arnold", "erika", "mustermann"); mssql_select_db("uni",$con); $rs = mssql_query($frage, $con); $s = mssql_num_fields($rs); 35 echo "Antwort ermittelt durch PHP-Script:<P>"; echo "<table border cellpadding=3>\n"; echo "<tr>"; for ($i=0 ; $i<$s ; ++$i) { $name = mssql_fetch_field($rs,$i); echo "<th>$name->name</th>"; } echo "</tr>"; antwort.php (Teil 2) while ($tupel = mssql_fetch_array($rs)) { echo "<tr>"; for ($i=0 ; $i<$s ; ++$i) { echo "<td>$tupel[$i]</td>"; } echo "</tr>"; } echo "</table>\n"; mssql_free_result($rs); mssql_close($con); ?> </BODY> </HTML> Demo: PHP 36 balken.php <?php $breite = $zahl*10; $hoehe = 30; $bild = imagecreate($breite, $hoehe); $farbe_balken = imagecolorallocate($bild, 0, 0, 255); $farbe_schrift = imagecolorallocate($bild, 255, 255, 255); ImageString($bild,3,$breite-16,8,$zahl,$farbe_schrift); header("Content-Type: image/png"); imagepng($bild); ?> 37 semester.php (Ausschnitt) $frage = "select name, semester from studenten order by name"; $rs = mssql_query($frage, $con); echo "<table border=1>\n"; echo "<TR><TH>Student</TH><TH>Studiendauer</TH></TR>"; while ($tupel = mssql_fetch_array($rs)) { echo "<TR>"; echo "<TD>$tupel[0]</TD>"; echo "<TD><IMG SRC=balken.php?zahl=$tupel[1]></TD>"; echo "</TR>\n"; } echo "</table>\n"; Demo: semester.php 38 torte.php <?php include ("../jpgraph/src/jpgraph.php"); include ("../jpgraph/src/jpgraph_pie.php"); $graph = new PieGraph(600,400,"auto"); $graph->SetShadow(); $graph->title->Set("Lehrbelastung der Professoren"); $graph->title->SetFont(FF_FONT1,FS_BOLD); $p1 = new PiePlot($daten); $p1->SetLegends($namen); $p1->SetCenter(0.4); $graph->Add($p1); $graph->Stroke(); ?> 39 lehre.php (Ausschnitt) $frage = "select name, sum(sws) from vorlesungen, professoren where persnr=gelesenvon group by name"; $rs = mssql_query($frage, $con); $i=0; while ($tupel = mssql_fetch_array($rs)) { $parameter .="namen[$i]=".$tupel[0]."&"; $parameter .="daten[$i]=".$tupel[1]."&"; $i++; } echo "<IMG SRC=torte.php?$parameter>"; Demo: lehre.php 40