Walter Doberenz, Thomas Gewinnus Borland Delphi 7 -Grundlagen, Profiwissen, Kochbuch Das umfassende Handbuch für die Win32-Anwendungsentwicklung ISBN-10: 3-446-41216-6 ISBN-13: 978-3-446-41216-3 Leseprobe 438 Kapitel 9 Datenbankprogrammierung ■ Eindeutig: Diese Einstellung verbietet, dass mehrere Datensätze den gleichen Wert in einem Sekundärindexfeld aufweisen dürfen. Ist ein Wert doppelt vorhanden, wird das Feld nicht indiziert und eine Warnung angezeigt. Nach Entfernen der Duplikate können Sie das Feld erneut indizieren lassen. ■ Gewartet (Standard): Diese (nur für Tabellen mit Schlüssel verfügbare) Einstellung bestimmt, ob der Sekundärindex nach jeder Veränderung der Tabelle automatisch aktualisiert wird. Das bedeutet eine Beschleunigung bestimmter Operationen, wie z.B. Abfragen. Ist die Option deaktiviert, so aktualisiert die Datenbankoberfläche den Index nur, wenn er verwendet wird, etwa beim Verknüpfen von Tabellen oder Ausführen von Abfragen. Ungewartete Indizes sollten vorzugsweise bei schreibgeschützten Tabellen zum Einsatz kommen. ■ Groß-/Kleinschreibung beachten: Normalerweise ist diese Option deaktiviert, so dass in der Sortierreihenfolge kein Unterschied z.B. zwischen den Einträgen "Borland Delphi" und "BORLAND DELPHI" festzustellen ist (die Reihenfolge entspricht dann der Stellung in der Tabelle). Einfachen Indizes mit aktivierter Groß-/Kleinschreibung wird automatisch der Feldnamen zugewiesen. Andererseits müssen Sie Indizes, bei denen die Schreibweise nicht berücksichtigt wird, beim Speichern selbst mit einem Namen benennen. ■ Absteigend: Auch diese Option ist im Normalfall deaktiviert, so dass Einträge in alphabetischer Reihenfolge (beginnend mit A) sortiert werden. Andernfalls würde, beginnend mit Z, abwärts sortiert. Praktische Erfahrungen zu dieser grundlegenden Thematik sammeln Sie in den Übungsbeispielen 9.3.2 und 9.3.3. 9.2 Datenbankzugriff mit Bound Controls Delphi verfolgt das Konzept der visuellen Programmierung nicht nur konsequent bei den Komponenten der Bedienoberfläche, sondern auch bei den Komponenten für den Datenbankzugriff. Diese werden wie "normale" Komponenten auf der Fensteroberfläche abgelegt und lassen sich über Eigenschaften und Methoden steuern. Auf Änderungen kann über Ereignisse reagiert werden. Ausgehend von einer Übersicht der vorhandenen Komponenten werden Sie mit den wichtigsten Einsatzmöglichkeiten vertraut gemacht. 9.2.1 Komponenten für Datenzugriff Komponenten dieses Typs sind zur Laufzeit unsichtbar. Sie stellen die Verbindung zur Datenbank her. Übersicht Die für uns interessanten Table- und Query-Komponenten entnehmen Sie der Seite "BDE" der Komponentenpalette (siehe auch Abschnitte 3.4.5 bis 3.4.7 in Kapitel 3): 9.2 Datenbankzugriff mit Bound Controls Table 439 Query Weiterhin wird die TDataSource-Komponente von der Seite "Datenzugriff" benötigt (warum erfahren Sie später): DataSource Datenbankanbindung Die grundsätzliche Vorgehensweise bei der Herstellung einer Datenbankanbindung ist immer die gleiche: ■ Über eine Table- oder eine Query-Komponente schaffen Sie sich das virtuelle Abbild einer oder mehrerer Tabellen. Legen Sie dazu die Eigenschaften DatabaseName und TableName bzw. DatabaseName und SQL fest. Eine Query-Komponente liefert das Ergebnis einer SQLAbfrage, während eine Table-Komponente immer eine Tabelle darstellt. ■ Verbinden Sie eine DataSource-Komponente über die DataSet-Eigenschaft mit einer Tableoder Query-Komponente. ■ Setzen Sie die Active-Eigenschaft von Table bzw. Query auf True, um die Verbindung zur Datenbank zu aktivieren. 9.2.2 Komponenten für Datensteuerung Die Komponenten dieser zweiten wichtigen Kategorie bleiben auch zur Laufzeit sichtbar. Sie fallen unter verschiedene gleichwertige Bezeichnungen, wie Bound Components, Bound Controls, datensensitive Komponenten, visuelle Dialogelemente, Datendialogelemente, und lassen sich über Eigenschaften (DataSource, DataField etc.) an bestimmte Datenquellen (Tabelle, Abfrage) anbinden, wobei eine DataSource-Komponente als Verbindungsglied dient. Veränderungen der Satzzeigerposition wirken sich auch auf den Inhalt des Steuerelements aus. Übersicht Welche Datendialog-Komponenten Delphi bietet, sehen Sie auf der Seite "Datensteuerung" der Komponentenpalette. Auf die für unsere Experimente besonders interessanten wird extra hingewiesen: 440 Kapitel 9 DBNavigator DBLookupListBox DBEdit DBText DBGrid Datenbankprogrammierung DBCheckBox DBMemo DBLookupComboBox Was Sie damit anfangen können, können Sie sich eigentlich denken: ■ DBNavigator Anzeige und Bearbeitungsmöglichkeit von Datensätzen in einem Tabellengitter. ■ DBGridSteuertasten für Datensatzzeiger (Vor, Zurück, Löschen, Neu, Abbrechen etc.). ■ DBEditAnzeige- und Eingabefeld für eine Textzeile. ■ DBMemo Anzeige und Eingabefeld für Mehrfachzeilen oder BLOB-Text. ■ DBTextAnzeige eines Feldes als Label. ■ DBCheckBoxAnzeige/Eingabe True/False in Abhängigkeit eines Tabellenfeldes. ■ DBLookupListBoxListenfeld, der gewählte Eintrag (ItemIndex) wird in der Tabelle gespeichert, die Listeneinträge werden aus einer zweiten Tabelle geladen! ■ DBLookupComboBoxComboBox, sonst wie DBLookupListBox. Verbinden mit den Datenzugriffskomponenten Die folgende Abbildung verdeutlicht das Grundprinzip: Wenn Sie die Datensteuerungskomponenten mit den Datenzugriffskomponenten verbinden wollen, schiebt sich die DataSource-Komponente quasi als "Mittler" dazwischen. zur Laufzeit sichtbar! Datenbank zur Laufzeit unsichtbar! Table DBEdit DataSource DBMemo DBNavigator 9.2 Datenbankzugriff mit Bound Controls 441 Vorgehensweise: ■ Binden Sie eine oder mehrere Bound Controls (DBText, DBEdit, DBMemo ...) über die DataSource-Eigenschaft an die DataSource-Komponente. Legen Sie anschließend den Feldinhalt über die DataField-Eigenschaft fest. Haben Sie diese Bearbeitungsreihenfolge eingehalten, können Sie den Feldnamen in einer Drop-down-Liste auswählen. ■ Wenn die Active-Eigenschaft der Table- oder Query-Komponente True ist, wird im Erfolgsfall der erste Datensatz der eingebundenen Tabelle/Abfrage angezeigt. Ist die SQL-Abfrage fehlerhaft oder existiert die Tabelle nicht, erscheint eine Fehlermeldung. Damit hätten Sie bereits eine (fast) fertige Eingabemaske. Ein Problem bleibt allerdings: Das Hinzufügen und Löschen von Datensätzen sowie eine Möglichkeit, zwischen den Datensätzen zu wechseln, fehlen bisher. All diese Wünsche erfüllt eine DBNavigator-Komponente, die Sie einfach über die DataSource-Eigenschaft an die DataSource-Komponente binden. Das war's auch schon! Mit einem Dutzend Mausklicks haben Sie bereits eine Datenbankapplikation erstellt, die in der Lage ist, Daten anzuzeigen, neue Datensätze hinzuzufügen und zu löschen. Die Funktionalität zum "Bewegen" zwischen den Datensätzen ist ebenfalls vorhanden. Den praktischen Einsatz lernen Sie im Übungsbeispiel 9.3.3 ("Eingabemaske mit Bound Controls") kennen. 9.2.3 Rave Reports-Komponenten Ihre Datenbankanwendung ist erst dann komplett, wenn die Abfrageergebnisse in ansprechender Form zu Papier gebracht werden. Bisher wurden Ihnen dazu die QuickReport-Komponenten bereitgestellt. Doch in Delphi 7 hat mit Rave Reports ein neuer Reportgenerator Einzug gehalten, und Sie als Programmierer haben jetzt natürlich dienstbeflissen alle Ihre Reports umzustellen. Halt, halt, ganz so schlimm ist es nicht gekommen. Haben Sie bereits Reports mit QuickReport entwickelt, können Sie diese natürlich auch weiternutzen bzw. Sie können wie gewohnt mit den QuickReport-Komponenten arbeiten. Für alle Neueinsteiger und Umstiegswilligen stellen wir an dieser Stelle die Arbeit mit Rave Reports vor, mehr zum Thema "QuickReport" finden Sie in unserem Buch [Borland Delphi – Datenbankprogrammierung]. Übersicht Die "Rave"-Seite der Komponentenpalette besticht bereits durch ihre Vielfalt: Der eigentliche Report-Designer ist hier jedoch noch nicht enthalten, Sie finden diesen im Verzeichnis \\Delphi7\Rave5\ als Rave.exe) als eigenständiges Programm. Über die Bedeutung der einzelnen Rave-Komponenten informiert Sie die folgende Tabelle: 442 Kapitel 9 Icon Datenbankprogrammierung Bezeichnung Erläuterung RvProject Über diese Komponente binden Sie die mit dem RaveDesigner erzeugten *.rav-Dateien in Ihr Delphi-Projekt ein, um diese mittels Execute-Methode anzuzeigen. RvSystem … ermöglicht die Vorgabe diverser Optionen und die Ausgabe als Vorschau, Druckausgabe oder *.NDR-Datei. RvNDRWriter … bietet die Möglichkeiten zum Erzeugen einer Druckdatei (*.NDR). RvCustomConnection … bietet Unterstützung für die Ausgabe von Array- oder nutzerdefinierten Daten. Der Programmierer stellt über die Ereignisse OnNext, OnEOF, OnFirst etc. quasi eine MiniDatenbank/-Tabelle zur Verfügung. RvDatasetConnection … unterstützt die Anbindung beliebiger TDatasetKomponenten an einen Report. RvTableConnection … dient dem Bereitstellen von BDE-TTable-Daten für einen Report (Einbindung als Direct Data View). RvQueryConnection … dient dem Bereitstellen von BDE-TQuery-Daten für einen Report (Einbindung als Direct Data View). RvRenderPreview … ermöglicht die Anzeige von NDR-Daten in einer Scrollbox. Mit den bereitgestellten Methoden können Sie eine komplette Druckvorschau realisieren. RvRenderPrinter … Ausgabe von NDR-Daten auf einem Drucker. RvRenderPDF … durch das Einbinden dieser Komponente steht Ihnen zusätzlich das Adobe Acrobat-Format für die Dateiausgabe zur Verfügung. RvRenderHTML … Ausgabe der Reportdaten im HTML-Format. RvRenderRTF … Ausgabe der Reportdaten im Rich Text-Format. RvRenderText … Ausgabe der Reportdaten im Text-Format. Wichtige Features Einige wesentliche Features des Rave Reports auf einen Blick: ■ Sowohl seiten- als auch bandorientierter Reportentwurf ■ Anbindung an TTable, TQuery, TDataset sowie nutzerdefinierte Datenmengen aus Ihrer Delphi-Anwendung ■ Direkte Anbindung an ADO-, BDE- oder DBX-Datenquellen ■ Externer Report-Designer1 1 Mit zusätzlicher Lizenz kann dieser auch eingebunden (DLL) und an den Enduser weitergegeben werden. 9.2 Datenbankzugriff mit Bound Controls 443 ■ Integrierte Druckvorschau ■ Integrierter Query-Builder ■ Relativ einfache Handhabung ■ Export im PDF-, HTML-, RTF- und Text-Format möglich ■ Eigener Rave Reports-Server für die Distribution von Reports über das Internet/Intranet im HTML- oder PDF-Format Der Designer Wie bereits erwähnt, handelt es sich um ein externes Programm, dessen Bedienung sich nicht wesentlich von Delphi unterscheidet: Die Vorgehensweise ist recht simpel: Erstellen Sie eine neue Reportdatei, können Sie in dieser beliebig viele Reports unterbringen. Diese Einzelreports können wiederum aus mehreren Seiten bestehen (z.B. Deckblatt, Listendarstellung und Zusammenfassung). Auf der linken Seite finden Sie die jeweiligen Eigenschaften des gewählten Objekts, über die Toolbar haben Sie die Möglichkeit, Komponenten auf dem Report zu platzieren. Die Struktur der Report-Datei (*.RAV) wird in der Baumansicht auf der rechten Seite dargestellt. Neben den einzelnen Reports sowie deren Seiten werden hier auch alle Datenverbindungen aufgelistet. Zwei Varianten bieten sich an: ■ Sie binden die Reports an Komponenten, die Sie in Ihr Delphi-Programm eingebunden haben (Direct DataView) 444 Kapitel 9 Datenbankprogrammierung ■ oder Sie nutzen die Möglichkeit des direkten Datenzugriffs per ADO, BDE oder ODBC (Driver Data View). Wir werden uns im Weiteren auf die erste Variante beschränken, da Sie hier die besten Einflussmöglichkeiten (Filtern, Gruppieren etc.) aus dem Delphi-Programm heraus haben. Doch bevor Sie vor lauter Theorie das Handtuch werfen, wollen wir uns lieber mit ein paar praktischen Beispielen beschäftigen. Konkrete Beispiele zum Thema "Rave Report" finden Sie unter 9.3.4 und 9.4.3 im Praxisteil des Kapitels. 9.3 Lernbeispiele für Einsteiger 9.3.1 Anlegen einer "Kundentabelle" Sie haben, beginnend mit dem Stand null, mehrere Etappen zu bewältigen: ■ Problemanalyse und Entwurf der Datenbankstruktur ■ Tabellenentwurf (Datenbankoberfläche, Paradox, SQL ...) ■ Oberflächenentwurf für den Datenzugriff (Delphi) ■ Zusammenstellen und Ausdruck von Berichten (Delphi/Rave Reports) Sie werden mit der wohl primitivsten Form einer relationalen Datenbank, einer einzigen Tabelle, beginnen. Darin sollen alle Kunden der Firma erfasst werden. Datenbankstruktur Da Sie es nur mit einer einzigen Tabelle zu tun haben, brauchen Sie sich keinen quälenden Überlegungen bezüglich der Datenbankstruktur hinzugeben. Wir einigen uns lediglich darüber, dass pro Person eine laufende Nummer, deren Namen, Anschrift (Straße, Ort, PLZ) und Telefonnummer abzuspeichern sind. Damit hätte unsere Tabelle folgenden Aufbau: Kunden Feldname Datentyp Größe Nr Zähler Name Alpha 50 Straße Alpha 50 Ort Alpha 50 PLZ Alpha 5 Telefon Alpha 30 Das Zählerfeld Nr ist kompatibel zum Datentyp Integer (lang), nur dass es sich immer automatisch um eins erhöht, wenn Sie einen neuen Kunden in die Tabelle aufnehmen. Wie Sie sehen, handelt es