Im zweiten Teil dieses Workshops lernen Sie verschiedene Möglichkeiten kennen, um Datensätze schnell aufzufinden. Hierzu werden bestimmte Datenfelder indiziert, d.h. es werden Indexes angelegt, mit deren Hilfe Datensätze in einem Bruchteil einer Sekunde gesucht werden können. Außerdem erfahren Sie, wie eine Datenbank-Tabelle nach bestimmten Datenfeldern sortiert werden kann. Am Ende dieses Workshops sollten Sie in der Lage sein, zu entscheiden, wann und wie sich Indexfelder einsetzen lassen und selbständig entsprechende Suchroutinen in Ihre Datenbank-Anwendung zu integrieren. Was sind Indexfelder und wann lassen sich diese sinnvoll einsetzen? Indexfelder spiegeln eine bestimmte Sortierfolge der Datensätze innerhalb der Datenbank wieder. Die Art und Weise der Sortierung lässt sich fast beliebig festlegen. So kann für ein Indexfeld ein einzelnens Datenfeld oder eine Kombination aus mehreren Datenfeldern festgelegt werden. Auch die Sortierfolge lässt sich individuell einstellen (auf- oder absteigende Sortierung). Indexfelder dienen in erster Linie der Perfomance des Datenbanksystems. So erfolgt die Suche eines bestimmten Datensatzes auch bei großen Datenmengen in sekundenschnelle. Als Beispiel sei hier eine Kunden-Datenbank mit 25.000 gespeicherten Kunden-Datensätze genannt. Die Suche eines ganz bestimmten Kunden anhand des Namens erfolgt in der Regel in weniger als einer Sekunde. Wie Sie jetzt bereits erahnen, lassen sich also Indexfelder immer dann sinnvoll einsetzen, wenn es um die Suche nach Inhalten bestimmter Datenbankfelder geht. Ein weiterer sehr vorteilshafter Aspekt ist das sortierte Blättern innerhalb des Datenbank-Bestandes. Ohne Indexfelder erfolgt das Blättern immer in der Reihenfolge, in der die Datensätze auch erfasst wurden. Soll jedoch das Blättern sortiert nach dem Kundennamen erfolgen, benötigen Sie ein Indexfeld auf das Datenfeld "Namen". Das Blättern innerhalb der Datensätze erfolgt dann alphabetisch nach Namen- ganz ohne zusätzlichen Quellcode. An dieser Stelle soll noch gleich ein dritter wichtiger Aspekt vorweggenommen werden, welcher bei sehr großen Datenbeständen eine nicht unerhebliche Perfomance-Rolle spielt. Gerade bei umfangreicheren SQL-Abfragen (SQL=enngl. "Structured Query Language") spielen Indexfelder in Sachen Geschwindigkeit eine große Rolle. Um beim obigen Beispiel zu bleiben (Suche nach Kundennamen), sind durchaus Differenzen von bis zu 30 Sekunden möglich. Mehr zur Datenbank-Abfragesprache "SQL" erfahren Sie im nächsten (dritten) Teil des Datenbank-Workshops. Der vierte Aspekt für den Einsatz von Indexfeldern ist das Herstellen von Relationen (Beziehungen) zweier oder mehrerer Datenbanktabellen miteinander. So lassen sich z.B. in der einen Tabelle alle Kunden-Stammdaten speichern, in einer weiteren Tabelle alle Aufträge der einzelnen Kunden. Um nun alle Aufträge eines bestimmten Kunden anzuzeigen, muß mindestens ein gemeinsames Datenfeld existieren, und zwar in allen in Relation zueinanderstehenden Tabellen. Hierfür eignet sich besonders die Kundennummer, da es jeden Kunden-Datensatz eindeutig kennzeichnet. Der Index wird in diesem Zusammenhang auch als Primärschlüssel bezeichnet (engl. primary key). Primärschlüssel besitzen die Eigenschaft, daß ihr Inhalt pro Tabelle nur einmal vorkommen darf, was bei der Kundennummer ja gegeben ist - im Gegensatz zum Kundennamen, welcher ja durchaus mehrfach vorkommen kann. In der Tabelle der gespeicherten Aufträge spricht man dann nicht von Primärschlüssel, sondern von Fremdschlüssel. Der Inhalt der Kundennummer ist in der Auftragstabelle ja auch nicht eindeutig, da für einen Kunden durchaus mehrere Aufträge gespeichert sein können, d.h. jeder kundenbezogene Auftrags-Datensatz hat ein und dieselbe Kundennummer. Bei dieser Art von Relation spricht man von einer 1:n - Beziehung, d.h. für einen Datensatz der Kundentabelle existieren 1...n Datensätze in der Auftragstabelle. Mehr zu Datenbank-Relationen in einem unserer nächsten Teile des Datenbank-Workshops. Erstellen von Indexes So viel zur Theorie, nun zur Praxis. Anhand der kleinen Adress-Datenbank aus Teil 1 des Workshops wird nachfolgend der Einsatz und die Programmierung von Indexfeldern Schritt für Schritt erläutert. Für welche Felder sollen Indexes erstellt werden? Die Antwort auf die Frage liegt ganz bei Ihnen: Erstellen eines Indexfeldes für "Namen" ' Datenbank öffnen Dim Db As Database Dim dbFile As String dbFile = App.Path + "\ADRESS.MDB" Set Db = Workspaces(0).OpenDatabase(dbFile, False, False) Index erstellen: Dim Index As New Index Index.Name = "Name" Index.Primary = False Index.Unique = False Index.Fields = "Name" ' Hinzufügen zur Indexes-Auflistung Db.TableDefs("Adressen").Indexes.Append Index Set Index = Nothing Erläuterungen: ... ' Sortierung in absteigender Sortierfolge 'Z-A oder 100-0) Index.Fields = "-Name" ... Jetzt muss nur noch das Index-Objekt der Datenbank-Tabelle (besser gesagt der Indexes-Auflistung der Tabelle) hinzugefügt werden. Dies geschieht über den Befehl: Db.TableDefs("Adressen").Indexes.Append Index Das war's dann auch schon. Mit Hilfe dieser paar Codezeilen haben Sie einen neuen Index erstellt. Dim Index As New Index Index.Name = "PlzOrt" Index.Primary = False Index.Unique = False Index.Fields = "PLZ;Ort" ' Hinzufügen zur Indexes-Auflistung Db.TableDefs("Adressen").Indexes.Append Index Set Index = Nothing Wie Sie sehen, erfolgt die Angabe mehrere Datenfelder getrennt durch das Semikolon-Zeichen (;). Dies ist dann auch schon die einzige Änderung gegenüber dem Erstellen von Indexes über ein einzelnes Datenfeld. Die Sortierung erfolgt bei Kombinationsfeldern zunächst nach dem ersten Datenfeld. Innerhalb gleicher Datenfeld-Inhalte erfolgt die Sortierung dann nach dem zweiten Datenfeld. Im obigen Beispiel werden die Datensätze also zunächst nach den Postleitzahlen sortiert. Innerhalb gleichlautender Postleitzahlen erfolgt die Sortierung dann nach Orten (A-Z). Primärindex (Primärschlüssel) Für die bisher erstellten Indexes wurde dir Primary-Eigenschaft immer auf False gesetzt. Zur Vollständigkeit soll nun noch ein Index als sogenannter Primärschlüssel erstellt werden, d.h. die Inhalte dieses Schlüssels müssen eindeutig sein - oder anders gesagt, es dürfen keine Datensätze gespeichert werden, mit doppelten Feldinhalten. Hierfür eignet sich eigentlich nur das Feld AdressNr, welches durch seine Eigenschaften so definiert ist, daß der Inhalt selbständig von der JET-Datenbank aktualisiert wird. Alternativ ließe sich auch eine Kombination aus Namen und Telefon-Nr. festlegen, wobei dann darauf zu achten ist, daß bei gleichlautenden Namen in jedem Falle unterschiedliche Telefon-Nummern gespeichert sein müssen. Dim Index As New Index ' Primärschlüssel (eindeutiger Index) Index.Name = "Nr" Index.Primary = True Index.Unique = True Index.Fields = "AdressNr" ' Hinzufügen zur Indexes-Auflistung Db.TableDefs("Adressen").Indexes.Append Index Set Index = Nothing Der Primärschlüssel spielt für den momentanigen Stand der Adressdatenbank keine wesentliche Rolle, könnte also auch weggelassen werden. In Hinsicht auf den weiteren Verlauf des Datenbank-Workshops soll jedoch die Möglichkeit bestehen, zu jeder Adresse unbestimmt viele Kontakte speichern zu können, welche in einer eigenen Datenbank-Tabelle "abgelegt" werden. Als Kontakt kommen Telefonanrufe, Briefverkehr, Emails oder auch Faxe in Frage. Mehr dazu in den nächsten Teilen des Workshops. Festlegen des aktiven Index für das Blättern und Anzeigen von Datensätzen Nachdem alle benötigten Indexes erstellt sind, kann die Datenbank-Tabelle (wieder) geöffnet werden. Nach dem Öffnen der Datenbank-Tabelle ist standardmäßig kein Index gesetzt, d.h. die Anzeige der Datensätze erfolgt in der Reihenfolge der Eingabe (ohne Berücksichtigung einer Sortierung). Das Festlegen des aktiven Indexes erfolgt durch eine einzige Codezeile: ' ggf. Tabelle öffnen Set Tabelle = Db.OpenRecordset("Adressen") ' Festlegen des aktiven Indexes Tabelle.Index = "Name" Nachdem Sie den aktiven Index über die Index-Eigenschaft des Tabellen-Objektes festgelegt haben, befindet sich der Datensatz-Zeiger auf den ersten Datensatz innerhalb der für den Index festgelegten Sortierfolge. Im obigen Beispiel erfolgt die Sortierung demnach alphabetisch (Ziffern, A-Z) nach Namen. Über die Methoden MoveFirst, MoveNext, MovePrevious und MoveLast kann die Datenbank also jetzt sortiert nach Namen "durchgeblättert" werden. Hinweis: Beispiel: Und noch eine Anmerkung zur Sortierung: Gezielte und schnelle Suche nach indizierten Datenfeldern Wie bereits eingangs erwähnt, ist ein wesentlicher Vorteil von Indexes die hervorragende Performance bei der Suche nach bestimmten Datensätzen (genauer gesagt: bei der Suche nach bestimmten Feldinhalten). So lassen sich Datensätze auch bei großen Datenmengen in sekundenschnelle (meist sogar in einem Bruchteil einer Sekunde) auffinden. Die Suche erfolgt hierbei über die eigens hierfür von der JET-Datenbank bereitgestellte Methode Seek. ' Festlegen des aktiven Indexes Tabelle.Index = "Name" ' Suchen nach "Meier" Tabelle.Seek "=", "Meier" Nach jedem Suchvorgang sollte geprüft werden, ob auch tatsächlich ein entsprechender Datensatz gefunden wurde: ' Prüfen, ob Suche erfolgreich If Not Tabelle.NoMatch Then ' Datensatz gefunden DatensatzAnzeigen Else ' kein Datensatz vorhanden MsgBox "Kein entsprechender Datensatz gespeichert." End If Die Erfolgs-Abfrage erfolgt über die Eigenschaft NoMatch, was soviel bedeutet, wie keine Übereinstimmung. Die Eigenschaft NoMatch gibt hierbei True zurück, wenn kein Datensatz gefunden wurde und dementsprechend False, falls ein entsprechender Datensatz existiert. Existiert ein entsprechender Datensatz, so befindet sich der Datensatz-Zeiger automatisch auf den gefundenen Datensatz, d.h. der Datensatz könnte. sofort in der Bildschirmmaske angezeigt werden. Dies erledigt die Prozedur DatensatzAnzeigen aus Teil 1 des Workshops. Erweiterte Suche und Erfolgskontrolle Wichtig Hierfür stellen wir Ihnen die nachfolgenden zwei Prozeduren vor, welche sich universell einsetzen lassen. Public Sub GetBookmark(Tabelle As Recordset, _ CurRec As String, CurIdx As String) ' Datensatz-Zeiger merken On Local Error Resume Next CurIdx = Tabelle.Index CurRec = Tabelle.Bookmark If Err Then CurRec = "" On Local Error GoTo 0 End Sub Public Function SetBookmark(Tabelle As Recordset, _ CurRec As String, CurIdx As String) As Integer ' Datensatz-Zeiger zurücksetzen Dim Result As Integer On Local Error Resume Next Result = True Tabelle.Index = CurIdx If CurRec <> "" Then Tabelle.Bookmark = CurRec If Err <> 0 Then Result = False Else Tabelle.MoveLast Tabelle.MoveNext End If On Local Error GoTo 0 SetBookmark = Result End Function Die erweiterte Suche nach einem Datensatz sieht dann folgendermaßen aus: Dim CurRec As String Dim CurIdx As String ' zunächst aktuellen Datensatz-Zeiger merken GetBookmark Tabelle, CurRec, CurIdx ' Suchen nach "Meier" Tabelle.Seek "=", "Meier" ' Prüfen, ob Suche erfolgreich If Not Tabelle.NoMatch Then ' Datensatz gefunden DatensatzAnzeigen Else ' kein Datensatz vorhanden MsgBox "Kein entsprechender Datensatz gespeichert." ' Datensatz-Zeiger auf ursprünglichen Datensatz zurücksetzen SetBookmark Tabelle, CurRec, CurIdx End If Beschreibung und Erläuterung der möglichen Suchvarianten In den bisherigen Beispielen wurde immer gezielt nach einer exakten Übereinstimmung gesucht. Im nachfolgenden lernen Sie alle Suchvarianten kennen, die Ihnen das JET-Datenbankmodul in Verbindung mit dem Seek-Befehl bereitstellt. Exakte Übereinstimmung (=) Tabelle.Seek "=", "Meier" Es wird nach einer Adressen mit dem exakten Namen Meier gesucht, nicht auch Meier Hugo oder Meierrich. Größer gleich (>=)Es wird nach einer Adresse gesucht, die entweder mit dem Suchbegriff übereinstimmt oder laut Sortierfolge hinter dem Suchbegriff eingereiht wird. Tabelle.Seek ">=", "Meier" Der Datensatz-Zeiger befindet sich entweder auf eine Adresse mit dem Namen oder Teilnamen Meier oder auf den in der Sortierfolge darauffolgenden Datensatz (z.B. Müller, Niebaum, Otter). Ggf. kann der Datensatz-Zeiger natürlich auch wieder auf einen NULL-Datensatz zeigen. Größer (>) Tabelle.Seek ">", "Meier" Der Datensatz-Zeiger befindet sich entweder auf einen hinter der Adresse Meier einsortierten Datensatz (z.B. Meier Hugo, Niebaum, Otter, ...) oder ggf. wieder auf einen NULL-Datensatz. Kleiner gleich (<=) Tabelle.Seek "<=", "Meier" Der Datensatz-Zeiger befindet sich entweder auf eine Adresse mit dem Namen oder Teilnamen Meier oder auf den in der Sortierfolge voranstehenden Datensatz (z.B. Ludwig oder Hintermeier). Ggf. kann der Datensatz-Zeiger natürlich auch wieder auf einen NULL-Datensatz zeigen. Kleiner (<) Tabelle.Seek "<", "Meier" Der Datensatz-Zeiger befindet sich entweder auf einen vor der Adresse Meier einsortierten Datensatz (z.B. Ludwig Georg, Hintermeier Artur, ...) oder ggf. wieder auf einen NULL-Datensatz. Gerade bei der Suche nach Namen ist die zweite Suchvariante zu empfehlen, da hier auch Teilnamen gefunden werden. Was jedoch vorkommen kann, ist daß nach Meier gesucht wurde, aber die Adresse von Otto Heinz angezeigt wird, da keine einzige Adresse mit dem Namen oder Teilnamen Meier gespeichert ist. Es ist nun also Ihre Entscheidung entweder eben die Adresse von Otto Heinz anzuzeigen oder einen entsprechenden Hinweis auszugeben. Für letztere Entscheidung, hier der entsprechende Quellcode: GetBookmark Tabelle, CurRec, CurIdx Tabelle.Seek ">=", "Meier" If Not Tabelle.NoMatch Then If Tabelle("Name") Like "Meier*" Then DatensatzAnzeigen Else MsgBox "Kein entsprechender Eintrag!" SetBookmark Tabelle, CurRec, CurIdx End If Else MsgBox "Kein entsprechender Eintrag!" SetBookmark Tabelle, CurRec, CurIdx End If Suche nach Kombinations-Indexfeldern Alle bisherigen Beispiele haben sich auf die Suche nach einem "einfachen" einzelnen Datenfeld bezogen. Handelt es sich bei dem aktiven Index jedoch um einen Kombinations-Index mehrerer Datenfelder, muss dies in der Syntax entsprechend korrekt angegeben werden. ' Festlegen des aktiven Indexes Tabelle.Index = "PlzOrt" ' Suchen nach "Müller" Tabelle.Seek "=", "97618", "Leutershausen" Praktischer Einsatz der Indexfelder und Suchroutinen in der Beispiels-Adressdatenbank Alle bisherigen Beispiele haben sich auf die Suche nach einem "einfachen" einzelnen Datenfeld bezogen. Handelt es sich bei dem aktiven Index jedoch um einen Kombinations-Index mehrerer Datenfelder, muss dies in der Syntax entsprechend korrekt angegeben werden. Nachfolgend soll nun eine entsprechende Suchroutine in die kleine Adress-Datenbank-Anwendung integriert werden. Hierzu wird ein Formular benötigt, welches sowohl die Auswahl des Suchfeldes als auch die Eingabe des Suchbegriffs selbst ermöglicht.
Anmerkung: Die Eingabe von PLZ und Ort muß direkt hintereinander, nur durch ein Leerzeichen voneinader getrennt erfolgen. Bsp.: 97618 Leutershausen Und hier der Quellcode für das Suchen-Formular frmSearch.frm: Option Explicit Private Sub Form_Load() ' Voreinstellung Suchauswahl Option1(0).Value = True End Sub Private Sub Form_QueryUnload(Cancel As Integer, _ UnloadMode As Integer) If UnloadMode <> 1 Then Cancel = True Command1_Click 1 End If End Sub Private Sub Form_Unload(Cancel As Integer) Set frmSearch = Nothing End Sub Private Sub Command1_Click(Index As Integer) ' Befehlsbuttons Select Case Index Case 0 Me.Tag = True Me.Hide Case 1 Me.Tag = False Me.Hide End Select End Sub Und jetzt der Aufruf des Suchenformulars aus der Adress-Anwendung heraus: Private Sub DatensatzSuchen() Static SuchText As String Static sIndex As Integer Dim Result As Boolean Dim CurRec As String Dim CurIdx As String Dim Feld As String ' Suchenformular aktivieren Load frmSearch With frmSearch .Option1(sIndex).Value = True .Text1.Text = SuchText .Show 1 Result = (.Tag = True) If Result Then sIndex = IIf(.Option1(0).Value = True, 0, 1) SuchText = .Text1.Text End If End With Unload frmSearch ' Suchvorgang starten If Result Then ' aktuellen Datensatz merken GetBookmark Tabelle, CurRec, CurIdx ' Index setzen Tabelle.Index = Choose(sIndex + 1, "Name", "PlzOrt") ' Suchen Tabelle.Seek ">=", SuchText Result = (Not Tabelle.NoMatch) If Result Then ' etwas gefunden...vergleichen ob übereinstimmt If sIndex = 0 Then Feld = Tabelle("Name") Else Feld = RTrim$(Tabelle("PLZ") + " " + Tabelle("Ort")) End If If Not (Feld Like SuchText + "*") Then Result = False End If End If ' Such-Auswertung If Result Then ' Datensatz anzeigen DatensatzAnzeigen Else MsgBox "Kein entsprechender Eintrag gespeichert!" ' Datensatzzeiger auf ursprünglichen Datensatz zurücksetzen SetBookmark Tabelle, CurRec, CurIdx End If End If End Sub Die Suchroutine kann natürlich noch erweitert werden. So ist es denkbar, daß nicht der erste gefundene Datensatz sofort in der Bildschirmmaske angezeigt, sondern zunächst eine Art Auswahlliste erstellt wird. Die Auswahlliste sollte alle Datensätze enthalten, die mit dem Suchbegriff übereinstimmen. Raffiniert wäre natürlich die Auswahlliste nur dann anzuzeigen, wenn mindestens zwei Suchtreffer vorliegen - bei nur einem Suchtreffer ist es sinnvoll den Datensatz sofort anzuzeigen. Ein weiterer Verbesserungspunkt der Suchroutine ist das Berücksichtigen oder auch Nicht-Berücksichtigen der exakten Groß-/Kleinschreibung... Sie sehen, die Suchabfrage lässt noch um einige Features erweitern. Probieren Sie es doch einfach aus (z.B. die zuvor erwähnte Auswahlliste). Zusammenfassung Ziel des zweiten Teils des Datenbank-Workshops war es Ihnen zu vermitteln, was Indexes sind und wie man diese für eine Datenbank-Tabelle erstellt und sinnvoll einsetzt. Sie sollten jetzt also in der Lage sein, Indexes gezielt einzusetzen, um zum einen eine sortierte Ausgabe der Datensätze zu erhalten und zum anderen entsprechende Suchroutinen zu integrieren. Nochmals zur Erinnerung:
Vorschau Teil 3 Im dritten Teil dieses Workshops werden Sie einige der zahlreichen Möglichkeiten der SQL-Abfragesprache kennenlernen. SQL (engl. "Structured Query Language") ist ein Bestandteil der JET-Datenbank-Engine, und eignet sich hervorragend für das Filtern (Suchen) mehrerer Datensätze einer Datenbanktabelle anhand ganz bestimmter Selektionskriterien (Abfragekriterien). So lassen sich z.B. mit einem einzigen Befehl alle Datensätze der Adressdatenbank heraussuchen, bei denen keine EMail-Adresse eingetragen ist oder alle Adressen in einem bestimmten PLZ-Gebiet. Dieser Workshop wurde bereits 25.895 mal aufgerufen.
Anzeige
![]() ![]() ![]() (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
Neu! sevCommand 4.0 ![]() Professionelle Schaltflächen im modernen Design! Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Tipp des Monats ![]() Dieter Otter PopUp-Menü wird nicht angezeigt :-( In diesem Tipp verraten wir Ihnen, wie Sie Probleme mit PopUp-Menüs umgehen können, wenn diese unter bestimmten Umständen einfach nicht angezeigt werden. TOP Entwickler-Paket ![]() TOP-Preis!! Mit der Developer CD erhalten Sie insgesamt 24 Entwickler- komponenten und Windows-DLLs. Die Einzelkomponenten haben einen Gesamtwert von 1605.50 EUR... |
||||||||||||||||||||||||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |