Exakte Suche nach Zeichenkette

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

Moderator: Moderatoren

Antworten
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 107
Registriert: Do, 06. Jul 2006 13:24

Exakte Suche nach Zeichenkette

Beitrag von Wonderer »

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...
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9343
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 358 Mal
Kontaktdaten:

Re: Exakte Suche nach Zeichenkette

Beitrag von Tom »

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
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 107
Registriert: Do, 06. Jul 2006 13:24

Re: Exakte Suche nach Zeichenkette

Beitrag von Wonderer »

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

Ich hatte eigentlich vermutet man kann dieses LIKE Text% Suchverhalten mit einem Befehl an-/abschalten.. :?
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Exakte Suche nach Zeichenkette

Beitrag von brandelh »

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
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9343
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 358 Mal
Kontaktdaten:

Re: Exakte Suche nach Zeichenkette

Beitrag von Tom »

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: 9343
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 358 Mal
Kontaktdaten:

Re: Exakte Suche nach Zeichenkette

Beitrag von Tom »

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
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 107
Registriert: Do, 06. Jul 2006 13:24

Re: Exakte Suche nach Zeichenkette

Beitrag von Wonderer »

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
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9343
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 358 Mal
Kontaktdaten:

Re: Exakte Suche nach Zeichenkette

Beitrag von Tom »

"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
Antworten