Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Wann verwende ich Find, Seek oder SQL ?

Begonnen von HansWerner, November 03, 2010, 11:34:28

⏪ vorheriges - nächstes ⏩

HansWerner

Access 2003 bietet verschiedene Möglichkeiten um Datensätze zu suchen.
Wann verwende ich welche Methode ?
Wann verwende ich Find, wann Seek, wann eine SQL-Anweisung ?
Von DLookup mal abgesehen.

MzKlMu

Hallo;
Mit Find sucht man im Formular (über das Recordset des Formulars), Seek kenne ich nicht und SQL ist SQL, mit SQL sucht man mit der Kriteriumsklausel (Where ...).
Es kommt halt darauf an, wo Du suchst.
Gruß Klaus

Jonny

Seek ist ein alter Befehl der statt find genommen werden kann.

Gruß

Johann

oma

Hallo,

seek ist kein alter Befehl!!

Die Methode SEEK ist die schnellste Methode zum Suchen von Datensätzen. Hiermit kann aber nur in Tabellen gesucht werden und das gesuchte Datenfeld muss  einen eindeutigen Index besitzen. Den Indexnamen kannst du im Tabellenentwurf unter Ansicht ---> Indizes finden. Dort sind die beim Tabellenentwurf festgelegten Indizes angeführt.

Nachteilig bei Seek ist, dass die gefundenen Daten nur zur Ansicht bereit stehen und die Suche nach mehrdeutigen Indizes nicht sinnvoll ist, da die Methode kein Weitersuchen kennt. Deshalb ist die Verwendung eher selten, das heisst aber nicht, dass das ein alter Befehl ist!


Gruß Oma
nichts ist fertig!

oma

#4
Hallo Hans-Werner,

Nach Daten suchen bzw. daten selektieren ist eine der häufigsten Aufgaben in eine DB
Du hast hierzu verschiedene Möglichkeiten:

1 -  Suchen und Weitersuchen mit der Methode  FindRecord
2  - Suchen und Weitersuchen mit der Methode  FindFirst im Recordset des Formulars
3  - Suchen mit der Methode SEEK
4  - Selektieren durch Filter im Formular setzen
5  - Selektieren im Recordset durch SQL mit WHERE-Klausel




1. Suchen:  FindRecord und FindNext
Im Kopf eines Formulars legst du ein Suchfeld txtSuchfeld, ein Button cmdSuchen  und ein Button  cmdWeitersuchen  an u. hinterlegst folgenden Code

Private Sub cmdSuchen_Click()
If IsNull(txtSuchfeld) Then Exit Sub
Me!Nachname.SetFocus
DoCmd.FindRecord Me!txtSuchfeld
End Sub



Private Sub cmdWeitersuchen_Click()
Me!txtNachname.SetFocus
DoCmd.FindNext
End Sub


Dies ist die einfachste Art für eine Suche nach einem Feld.   Benutzt wird die Methode FindRecord.  Die Methode verlangt, dass das Suchfeld nicht leer ist und dass das Feld, indem gesucht werden soll, im Formular sichtbar ist und den Focus besitzt. Zur Methode können weitere Parameter eingesetzt werden. Die Methode FindNext übernimmt den Suchbegriff und alle anderen gesetzten Parameter von FindRecord


2. Suchen:  Find und RecordsetClone

Im Formularkopf legst du ein Kombinationsfeld cboSuchfeld und ein Button cmdWeitersuchen an
Für das  Ereignis "Nach Aktualisierung" für Kombinationsfeld cboSuchfeld  folgender Code:

Private Sub cboSuchfeld_AfterUpdate()
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.FindFirst "Nachname=' " & Me!cboSuchfeld & " ' "
Me.Bookmark = rs.Bookmark
End Sub



bzw. für Weitersuchen:

Private Sub bntWeitersuchen_Click()
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.FindNext "Nachname='" & Me!cboSuchfeld & "'"
If Not rs.NoMatch Then
  Me.Bookmark = rs.Bookmark
Else
MsgBox "nix mehr da"
End If
End Sub


Die Methode FindRecord verlangt immer , dass das zu suchende Feld aktiviert ist.  Dies ist bei  der Methode Find und RecordsetClone im Einzelformular nicht der Fall.
Mit rs.FindFirst "Nachname=' " & Me!cboSuchfeld & " ' "  (es wird mit Text gesucht) wird im Recordset des Formulars gesucht und nach dem Finden mit  Me.Bookmark = rs.Bookmarkkönnte wird der gefundene Datensatz zum aktuellen Datensatz im Formular gemacht.

Das Suchfeld kann natürlich auch als einfaches Textfeld gestaltet sein, um auch mit Teilstrings zu suchen Dann muss allerdings mit :  
Me.RecordsetClone.FindFirst  "Nachname Like ' * " & Me!txtSuchfeld & " * ' "      gesucht werden!


3. Suchen:  SEEK

Zur Suche erstellst du ein ungebundenes Formular mit dem Textfeld txtSuchfeld und den Button cmdSuchen

Private Sub cmdSuchen_Click()
Dim db As DAO.Database, rs As DAO.Recordset

Set db = CurrentDb
Set rs = db.OpenRecordset("tblKunden", dbOpenTable)

If IsNull(Me!txtSuchfeld) Then Exit Sub

rs.Index = "idxKundenNr"
rs.Seek "=", Me!txtSuchfeld

If Not rs.NoMatch Then
  Me!Firma = rs!Firma
  Me!Straße = rs!Straße
  Me!PLZ = rs!PLZ
  Me!Ort = rs!Ort
Else
   MsgBox "nix da"
End If

End Sub


4. Selektieren:  Filter setzen

Im Formularkopf legst du ein Textfeld txtSuchfeld  und die Button cmdFiltern  und cmdAlle  an
für  Button Filtern mit Ereignis BeimKlicken  folgender Code:

Private Sub cndFiltern_Click()
Me.Filter = "Nachname LIKE ' * " & Me!txtSuchfeld & " * ' "
Me.FilterOn = True
End Sub


bzw.  für den Button bnt Alle:


Private Sub  cmdAlle_Click()
Me.FilterOn = False
End Sub


Mit   Me.Filter = "Nachname LIKE ' * " & Me!txtSuchfeld & " * ' "    wird ein Filter mit *Nachname* gesetzt, d.h. es können auch Teilbegriffe des Namens zur Suche verwendet werden.   Mit  Me.FilterOn = True   wird der Filter aktiviert und mit   Me.FilterOn = False   wieder aufgehoben.

5. Selektieren:  SQL mit Where-Klausel

Im Formularkopf legst du ein Textfeld txtSuchfeld  und die Button cmdAuswahl  und cmdAlle  an, für  Button Auswahl mit Ereignis BeimKlicken  folgender Code:


Private Sub  cmdAuswahl_Click()
If IsNull(txtSuchfeld) Then Exit Sub
Me.RecordSource = "Select * from tblPersonal" _
& " WHERE txtNachname LIKE' * " & Me!txtSuchfeld & " * ' "
End Sub


zw.  für den Button bnt Alle:

Private Sub  cmdAlle_Click()
Me.RecordSource = "SELECT * From tblPersonal"
End Sub


Mit    "Select * from tblPersonal  WHERE txtNachname LIKE' * " & Me!txtSuchfeld & " * ' "   wird direkt in der Tabelle (oder Abfrage) der Datenherkunft gesucht, und mit    Me.RecordSource     die Datenherkunftsquelle des Formulars bestimmt.

Diese Methode ist für häufiges Suche/Selektieren wohl die beste, da problemlos nach mehreren Feldern selektiert werden kann. Hierzu in der Anlage mal ein kleines Beispiel


Es gäbe noch so manches zu den einzelnen Methoden zu sagen, bzw. gibt es noch allerlei Tricks zur Erweiterungen der Methoden.
Ich denke aber, ich habe dir mal einen kleinen Überblick verschafft.

Gruß Oma


[Anhang gelöscht durch Administrator]
nichts ist fertig!

HansWerner

Vielen Dank für die ausführliche Antwort.
Du hast dir eine Menge Arbeit gemacht.
Konkret noch folgendes Beispiel nachgeschoben:
Ich habe eine Kundendatenbank bzw. etwas ähnliches mit Vorname, Nachname, Telefonnummer usw.
Nun möchte ich mit einem Formular (Ungebundene Felder) nach einer beliebigen Kombination aus Eingabewerten suchen können. Also nur nach dem Vornamen oder Nachnamen oder einer Kombination aus Vornamen und Nachnamen usw. Jedes einzelne Feld kann also leer sein oder auch nicht.
Momentan habe ich mir einen Suchstring zusammengebastelt und Find benutzt.
Es wird also kein Datensatz, ein Datensatz oder auch mehrere Datensätze gefunden.
Wird kein Datensatz gefunden wird eine entsprechende Meldung ausgegeben; werden mehrere Datensätze ausgegeben so wird die Anzahl der gefundenen Datensätze ausgegeben damit der Nutzer seine Suche verfeinern kann. Wird nur ein Datensatz gefunden so sollen in einem Unterformular die entsprechenen Adressen des Kunden ausgegeben werden (Können mehrere sein). Wie ich ein Unterformular in der Datenblattansicht mit mehreren Zeilen benutze ist mir auch noch nicht klar.
Die Tabelle benutzt natürlich einen Autowert als eindeutigen Index da Vorname, Nachname usw. nie eindeutig sind.
Ist der Ansatz mit dem zusammenbasteln des Suchstrings und der Verwendung von Find der beste ? ???

Shai

#6
Man erstellt aus den gegeben Suchoptionen eine SELECT -Anweisung (also eine SQL-Abfrage) und schiebt diese in in die RecordSource des Unterformulars.
Zum Beispiel.
Dein Hauptformular enthält die Felder NachName, Vorname, Strasse, Ort
sowie ein Unterformular namens "frmKundenUF"

Du erstellst eine Routine zur Erstellung des Suchstrings:
Private Sub KundenSuchen ()
  Dim strSQL as String
 
  strSQL = "SELECT * FROM Kunden WHERE "
  if Me!NachName > "" then  
      strSQL = strSQL & " NachName like '" & Me!NachName & "*' AND "
  end if
  if Me!VorName > "" then  
      strSQL = strSQL & " VorName like '" & Me!VorName & "*' AND "
  end if
  if Me!Strasse > "" then  
      strSQL = strSQL & " Strasse like '" & Me!Strasse & "*' AND "
  end if
  if Me!Ort > "" then  
      strSQL = strSQL & " Ort like '" & Me!Ort & "*' AND "
  end if
 ' das WHERE oder das AND hinten abschneiden
 if right$(strSQL,6) = "WHERE " then
      strSQL = left$ (strSQL, len(strSQL - 6)
 else
      strSQL = left$ (strSQL, len(strSQL - 4)
 end if
  ' msgbox("Die Anweisung lautet: " & strSQL)
 Me.frmKundenUF.Form.RecordSource = strSQL
End Sub


Achte auf die Feinheiten: Vor den "-Zeichen sind Hochkomma ' versteckt.
Heraus kommt dann eine Anweisung wie z.B.
SELECT * FROM Kunden WHERE NachName like 'Müll*' AND Ort like 'Mann*'
Wenn Du sehen willst, enferne das Hochkomma vor der msgbox-Zeile.

Dann erstellst Du einen Button "Suchen" im Formular und rufst diese Routine auf:
Private Sub btnSuchen_Click()
  KundenSuchen
End Sub


Ich hoffe, in der Routine ist kein Fehler drin, das habe ich ohne Test einfach schnell hier reingetan.
zu viele Leute denken in Excel.

HansWerner

Danke, wieder was gelernt.
Du bastelst also auch einen String zusammen und verwendest dann die RecordSource Eigenschaft anstelle der Find Methode.
Noch eine Frage zur RecordSource Eigenschaft.
Wenn ich diese während des Programmablaufes ändere, wird dann das entsprechende Formular bzw. Unterformular automatisch aktualisiert ? Mit Requery funktioniert es bei mir nicht.
Als Ausschnitt (Das Formular ist bereits geöffnet):

Unterformular ausgeben, Schüler ist Index also vom Type Long
Innerhalb von With bezogen auf den Recordset
Die SQL Abfrage funktioniert
Me ist das Hauptformular, SchülerUndAdressen ist die Zwischentabelle zwischen der Tabelle Schüler und der Tabelle Adressen

Schüler = CStr(.Fields("Schüler").Value)
SQLstring = "SELECT * FROM Adressen INNER JOIN SchülerUndAdressen ON SchülerUndAdressen.Adresse = Adressen.Adresse WHERE SchülerUndAdressen.Person = " & Schüler & " ;"
Me.Schüler_Adressen_Unterformular.Form.RecordSource = SQLstring
Me.Schüler_Adressen_Unterformular.Form.Requery


oma

#8
Hallo Hans-Werner,

schaue dir doch mal mein Beispiel im Anhang an.

Das kannst du doch mit wenig Aufwand für deinen Fall anwenden, indem du nur die Felder Nachname und Vorname verwendest.

Vom Prinzip ist das wie der Lösungsvorschlag von Shai, nur etwas kompakter geschrieben.
Die Suchbegriffe sind in eine Extra-Formular geschrieben. Somit kannst du das Formular als "normales" Formular benutzen aber auch das Suchformular aufrufen.

Anbei noch einmal den Code zum dynamischen Erstellen eines SQL-Strings für Zahlen, Text oder Datumsfelder:

Private Sub Start_Click()
'Beispiel für dynamischer SQL-String mit Text, Zahl, Datum
Dim krit As String, strSQL As String

    If Not IsNull(Me!Firma) Then krit = krit & " And Firma Like '*" & Me!Firma & "*'"
    If Not IsNull(Me!Ort) Then krit = krit & " And Ort = '" & Me!Ort & "'"
    If Not IsNull(Me!UmsatzVon) Then krit = krit & " AND Umsatz >=" & Me!UmsatzVon
    If Not IsNull(Me!UmsatzBis) Then krit = krit & " AND Umsatz <=" & Me!UmsatzBis
    If Not IsNull(Me!GründungVon) Then krit = krit & " AND DatumGründung >= " & Format(Me!GründungVon, "\#yyyy-mm-dd\#")
    If Not IsNull(Me!GründungBis) Then krit = krit & " AND DatumGründung <= " & Format(Me!GründungBis, "\#yyyy-mm-dd\#")
 
    strSQL = "SELECT * FROM tblKunden "
    If krit <> "" Then strSQL = strSQL & "WHERE" & Mid(krit, 5)
   
    Forms!Kunden!Kunden.Caption = " Auswahl Kunden"
    Forms!Kunden!Kunden_UF.Form.RecordSource = strSQL
End Sub



Gruß Oma
nichts ist fertig!

Shai

Ja, Requery des Unterformulars erfolgt automatisch nach Veränderung der RecordSource-Eigenschaft
zu viele Leute denken in Excel.

HansWerner

Hallo Shai,

bei mir erfolgt leider keine Aktualisierung des Formulars wenn ich RecordSource ändere.
Wie wird eigentlich die Tabelle auf die Felder des Formulars abgebildet ?
Was, wenn ich in dem Formular mehr oder weniger Felder habe wie in der Tabelle ?
Müssen alle Felder vorhanden sein oder genügt es wenn diese den gleichen Namen besitzen ?

Jonny

Hallo Werner,
wie hast Du denn die Felder auf den Formular, als gebunden oder als ungebundene Felder?
Aufgrund deiner Fragestellung und das sich nichts aktualisiert vermute ich das die Felder ungebunden sind.
Normalerweise nimmt man gebunde Felder und die aktualisieren sich beim Zuordnen des Recordsets.
Es müssen im Form nicht alle Felder vom DS sein. Aber Achtung wenn das Formular für die Dateneingabe dient
müssen die Pflichtfelder vorhanden sein.

Hallo Oma,
ich hätte meine Antwort etwas ausführlicher schreiben sollen. Seek ist ein alter Befehl (alt heißt ja nicht
schlecht siehe Feldnamen nur mit Buchstaben und Ziffern). Wenn ich mich richtig erinnere habe ich den
Befehl schon bei einer Triumph-Adler mit Lokomotive-Basic eingesetzt.

oma

Hallo Jonny,

hast Recht, ich habe "alt"  als "nicht mehr aktuell" aufgefasst. SEEK ist eine alte  und immer noch aktuelle Methode ;D!

Gruß Oma
nichts ist fertig!

HansWerner

Hallo Johnny,

der Thread wird schon etwas länger.
Möchte jedoch keinen neuen aufmachen, da ich hier so hilfreiche Antworten finde.
"Normalerweise nimmt man gebundene Felder"
Schön, schön, aber was ist normal bzw. in welchen Fällen sollte oder muß man gebundene Felder verwenden.
Soweit ich das ausprobiert habe kann ich bei gebundenen Feldern nichts eingeben.
Die dienen also nur der Ausgabe ?
Wollte eigentlich ein Formular basteln mit dem ich sowohl einen Datensatz suchen und anzeigen, löschen oder auch neu eingeben kann. Dazu muß ich nach meiner Meinung nach ungebundene Formularfelder verwenden.
Also doch nicht RecordSource verwenden sondern find ? ???

DF6GL

Hallo,

also ich finde, da werden sich Gedanken um des Kaisers Bart gemacht   ;)  8)
und gehen an der Lösung des Problems vorbei.


Es gibt als Basis:

1) Tabellen mit Feldern bestimmter Datentypen, die Daten speichern und als Datensatzkennung ein Primärschlüsselfeld haben (sollten!)
2) Beziehungen zwischen den Tabellen, wobei diese durch die Angabe der Schlüsselfelder (Primär- und Fremdschlüssel) definiert werden.
3) Abfragen, die u. a. solche in Beziehung stehenden Tabellen zu einer "Sicht" zusammenfassen.
4) Formulare, die über ihre Eigenschaft "Datenherkunft" an eine Tabelle (oder Abfrage) "gebunden" sind , d. h. ihre Daten eben von dort beziehen.
5) In Formularen gebundene Felder (Steuerelemente), die wiederum die entspr. Feldinhalte anzeigen oder darstellen können und weil gebunden, diese auch wieder in die Datenherkunft (spriche Tabelle/Abfrage) zurückspeichern.
6) Formulare sind interaktiv, d. h. man kann Daen hinzufügen, ändern, löschen und auch die im Formular selber oder bei den einzelnen Steuerelementen auftretenden Ereignisse reagieren. (z. B: per VBA als Ereignisprozeduren).

Allein mit diesen "Objekten" kommt man schon ein ganzes Stückweit voran.

Daneben sind natürlich auch ungebundene Formulare oder auch lediglich Steuerelemente einsetzbar. Die zeigen halt, weil eben ungebunden, nicht "automatisch" irgendwelche Feldinhalte aus der Datenherkunft (die zudem ja auch nicht vorhanden sein muß) an, sondern deren Werte müssen von Hand (soll heißen per Prozedur oder durch Eintippen) eingetragen werden. Sollen diese Werte dann auch noch (irgendwo) gespeichert werden, muß das eben auch per Code geschehen, weil in diesem Fall die "Access-Automatik" halt fehlt.

Soll heißen:  ungebundene Steuerelemente werden in den meisten Fällen zur Ablaufsteuerung in Formularen verwendet, z. B. Kombifelder zur Suche bestimmter Datensätze, bzw. nur als Grundlage für den Zusammenbau des u. g. SQl-Strings (Abfrage) für ein Formular.


Um nun diese Datensätze zu finden, können die angesprochenen   Methoden benutzt werden. Meistens ist es aber nur:

SQL-String mit Where-Condition für die Datenherkunft in einem Formular. Dadurch werden NUR die Datensätze aus der Tabelle gelesen, die den Kriterien entsprechen.

Filter-Methode des Formulares:  Damit werden die schon dem Formular vorher angebotenen Datensätze lediglich für die Anzeige eingeschränkt. Ein Abfrage (Auslesen aus) der Tabelle erfolgt dabei nicht mehr.

Fast alles über Formulare Gesagtes gilt auch für Berichte, nur dass Berichte nicht interaktiv sind..(Keine Daten über die gebundenen Felder eingebbar sind und ändern können.

Seek ist wie gesagt weniger üblich in der Access-Umgebung.