Exakte Suche nach Zeichenkette

Eigentlich ist mir die Frage peinlich, aber es kann sonst niemand helfen ... :)

Moderator: Moderatoren

Exakte Suche nach Zeichenkette

Beitragvon Wonderer » Do, 31. Mär 2016 13:10

Hallo,

beim Debuggen ist mir gerade etwas aufgefallen, was mich später dann noch zu Problemen führen würde, weil die erwarteten DB-Daten so nicht vorhanden sind.

folgende ausgelagerte Befehls-Abfolge habe ich getestet:
Code: Alles auswählen
procedure Main
    // Hauptmodell anlegen wenn nicht vorhanden
    if file( "DB_DUMMY.DBF" )
       erase ("DB_DUMMY.DBF")
    endif
   
    aStruct := { { "ID", "N", 2, 0 }, ;
              { "NAME", "C", 32, 0 } }
    DbCreate( "DB_DUMMY.DBF", aStruct )
   
    SELECT 103
   USE ( "DB_DUMMY.DBF" )
   
    APPEND BLANK
       REPLACE ID WITH 1
       REPLACE NAME WITH "ELEMENT 1"
    APPEND BLANK
       REPLACE ID WITH 3
       REPLACE NAME WITH "ELEMENT Nummer 3"
    APPEND BLANK
       REPLACE ID WITH 4
       REPLACE NAME WITH "ELEMENT Nummer 4"
    APPEND BLANK
       REPLACE ID WITH 5
       REPLACE NAME WITH "Nummer - 5"
       
    INDEX ON NAME TO DummyName
    SET INDEX TO DummyName
    SET ORDER TO 1
    SET EXACT ON
    SET SOFTSEEK OFF
   
    cFind := "element"
    SEEK cFind
    if len(rtrim(cFind)) != len(rtrim(NAME)) .and. Found()
        ? ("unterschiedlicher Inhalt mit FOUND->TRUE & EOF->FALSE")
      ? "gesucht:  '"+cFind+"'"
      ? "gefunden: '"+NAME+"'"
    endif
   
    cFind := "ELEMENT Nummer"
    SEEK cFind
    if len(rtrim(cFind)) != len(rtrim(NAME)) .and. Found()
        ? ("unterschiedlicher Inhalt mit FOUND->TRUE & EOF->FALSE")
      ? "gesucht:  '"+cFind+"'"
      ? "gefunden: '"+NAME+"'"
    endif

    // Workaround...
    cFind := "ELEMENT Nummer"
    SEEK (cFind + space( len(NAME)-len(cFind) ))
    if len(rtrim(cFind)) != len(rtrim(NAME)) .and. Found()
        ? ("unterschiedlicher Inhalt mit FOUND->TRUE & EOF->FALSE")
      ? "gesucht:  '"+cFind+"'"
      ? "gefunden: '"+NAME+"'"
    endif

return


Wenn ich nach dem exakten String suchen möchte, dann muss ich die zu suchende Zeichenkette erweitern auf die Länge des Datenbank-Feldes, andernfalls liefert mir SEEK den ersten Datensatz der mit genau dieser Zeichenkette anfängt aber dennoch ungleich sein kann :doubt:

Ich habe SOFTSEEK OFF und EXACT ON, was muss ich vor dem SEEK in der Datenbank setzen damit ich den Workaround nicht benötige?

danke schon mal für die Hilfe...
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
 
Beiträge: 107
Registriert: Do, 06. Jul 2006 12:24

Re: Exakte Suche nach Zeichenkette

Beitragvon Tom » Do, 31. Mär 2016 13:29

DbSeek(<Zeichenkette>) findet den ersten Datensatz, der mit <cZeichenkette> beginnt. Je länger/exakter die Zeichenkette ist, umso genauer ist das Ergebnis. Die Frage lautet also, welches Ergebnis Du willst.

DbSeek("Element 1") würde "Element 1" zuerst finden, und, wenn es dieses nicht gibt, zum Beispiel "Element 10". Wenn Du genau "Element 1" finden willst, musst Du den Suchausdruck auf die Länge des Feldes/Indexausdrucks erweitern:

DbSeek(PadR("Element 1",32)) // findet "Element 1" und auch nur dieses, denn "NAME" enthält in diesem Fall "Element 1", gefolgt von 23 Leerzeichen.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
 
Beiträge: 6680
Registriert: Do, 22. Sep 2005 22:11
Wohnort: Berlin

Re: Exakte Suche nach Zeichenkette

Beitragvon Wonderer » Do, 31. Mär 2016 13:48

Aaah, Ok... PadR - das hilft mir auch weiter..

Ich hatte eigentlich vermutet man kann dieses LIKE Text% Suchverhalten mit einem Befehl an-/abschalten.. :?
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
 
Beiträge: 107
Registriert: Do, 06. Jul 2006 12:24

Re: Exakte Suche nach Zeichenkette

Beitragvon brandelh » Do, 31. Mär 2016 13:53

Die Feldlänge sollte man hier dynamisch ermitteln ... denn die kann sich eventuell mal ändern und dann denkt keiner an diese Suche ;-)
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
 
Beiträge: 13273
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim

Re: Exakte Suche nach Zeichenkette

Beitragvon Tom » Do, 31. Mär 2016 14:09

Die Feldlänge sollte man hier dynamisch ermitteln ...


Kann man machen, im Hinblick auf weitere Veränderungen sollte man möglicherweise sogar. Dann aber optimiert, also einmalig für Suchroutinen, die möglicherweise mehrfach angesprochen werden, denn auch "FieldInfo(<nPos>,FLD_LEN)" kostet irgendwann Zeit. Bei zusammengesetzten Suchausdrücken muss man mit IndexKey() und OrdKey() arbeiten - und dann ggf. mit dem Makrooperator:

Code: Alles auswählen
nSearchLen := Len(&(OrdKey()))
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
 
Beiträge: 6680
Registriert: Do, 22. Sep 2005 22:11
Wohnort: Berlin

Re: Exakte Suche nach Zeichenkette

Beitragvon Tom » Do, 31. Mär 2016 14:55

Ergänzung: Man kann es sich via PP relativ einfach machen und SEEK generell auf eine eigene Funktion verbiegen, die erstens prüft, ob nach Zeichenketten gesucht wird und zweitens dann die Ergänzung auf die Länge generell vornimmt.
Code: Alles auswählen
#xtranslate SEEK <xSeekValue> => MySeek(<xSeekValue>) // am Anfang des PRG

FUNCTION MySeek(<xSeekValue>) // später
LOCAL nLen := 0
IF xSeekValue # NIL .AND. ValType(xSeekValue) == "C"
  nLen := Len(&(OrdKey()))
  RETURN DbSeek(PadR(xSeekValue,nLen)) // hier NICHT 'SEEK' verwenden, da die Funktion sonst auf sich selbst zeigen würde!
ENDIF
RETURN DbSeek(xSeekValue)


Allerdings würden dann alle SEEKs, die in PRGs enthalten wären, die die Translate-Direktive enthielten, auf diese Funktion verbogen werden, und die Suche wäre dann auch immer "exakt" (und außerdem etwas langsamer). Ich hab's auch nur gepostet, um mal auf die Idee hinzuweisen. Der PP ist ein sehr mächtiges Werkzeug.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
 
Beiträge: 6680
Registriert: Do, 22. Sep 2005 22:11
Wohnort: Berlin

Re: Exakte Suche nach Zeichenkette

Beitragvon Wonderer » Fr, 01. Apr 2016 8:20

Dank an euch beide!

Das mit der dynamischen Länge war mir auch gleich in den Sinn gekommen.

Interessant was ich zu XTRANSLATE im Referenzhandbuch bzgl. der 4signifikanten Stellen gelesen habe:
Code: Alles auswählen
#translate something => trans1
#translate somethingelse => trans2


Bei beiden Schlüsselwörtern würde mit 'trans2' ersetzt und hier braucht man stattdessen XTRANSLATE?!? :o
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
 
Beiträge: 107
Registriert: Do, 06. Jul 2006 12:24

Re: Exakte Suche nach Zeichenkette

Beitragvon Tom » Fr, 01. Apr 2016 8:26

"xtranslate" gleicht "translate". Der Unterschied besteht darin, dass "translate" gemäß dBASE/Clipper-Konvention(en) nur die ersten vier Zeichen für Vergleichsoperationen heranzieht, während "xtranslate" den gesamten Schlüsselbegriff verwendet. Bei "SEEK" wäre das egal, weil es ohnehin nur vier Zeichen lang ist.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
 
Beiträge: 6680
Registriert: Do, 22. Sep 2005 22:11
Wohnort: Berlin


Zurück zu Newbie

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast