[gelöst] SQL: Suche mit Like geht nur "zum Teil"

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

[gelöst] SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Aliobaba »

Hallo,

ich finde ein seltsames Verhalten bei einem SQL-Befehl.
Gearbeitet wird mit Lazarus - Linux/Kubuntu, den Zeos-Komponenten und einer SQLite Datenbank.

Code: Alles auswählen

 
   sss := 'Buch' ;
 
   sss := ( '%' + sss + '%' ) ;   // funktioniert wie es soll: findet alle genannten Wörter
   // sss :=  ( sss + '%' ) ;       // findet nichts            : erwartet wird:   Buch(?) und Buchdrucker
   // sss :=  ( '%' + sss ) ;       // findet auch nichts    : erwartet wird:   Buch(?) und Handbuch
 
  Form2.Edit1.Text:=sss;
 
  With form1.Qtext do
  Begin
     SQL.Clear;
     SQL.Add('SELECT * FROM tText');
     SQL.Add('WHERE (rText LIKE :Such1 Or rTitel LIKE :Such1 Or rHinweis LIKE :Such1)');
     SQL.Add('ORDER BY UPPER(rTitel)');
     Params.ParamValues['Such1'] := sss;
     Open;
  end;

Wenn in der Datenbank die Worte vorkommen:
z.B.:
Buch / Handbuch / Buchdrucker / Handbuchinhalt

Dann findet die nicht auskommentierte obige Zeile alle Worte und die beiden auskommentierten Zeilen (wenn nicht auskommentiert) nichts??

Obwohl
1. in "Form2.Edit1.Text" der richtige Begriff übernommen ist, also %Buch% , %Buch oder Buch%
und obwohl
2. ein SQL-Editor (SQLite-Manager) die Befehle in allen drei Variationen fehlerfrei abarbeitet.

Aliobaba
Zuletzt geändert von Aliobaba am So 22. Jan 2017, 15:51, insgesamt 3-mal geändert.
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Eb
Lazarusforum e. V.
Beiträge: 238
Registriert: Di 5. Feb 2008, 15:32
OS, Lazarus, FPC: Linux Mint - Laz 2.2.0
CPU-Target: 64Bit
Wohnort: Stuttgart

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Eb »

Du könntest zur weiteren Eingrenzung des Problems mal versuchen die Where-Clause ohne Parameter, sondern direkt als String zu schreiben:

Bei mir geht (mit zeos und mysql) folgendes korrekt:

Code: Alles auswählen

sqlstatement.ADD('where v.englisch like ''%' + where_klausel_like + '%'' '); 
 
sqlstatement.ADD('where v.englisch like ''' + where_klausel_like + '%'' ');
 
sqlstatement.ADD('where v.englisch like ''%' + where_klausel_like + ''' ');

MmVisual
Beiträge: 1466
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von MmVisual »

Das Quoting eines Strings per SQL String ist schlecht, besser per Parameterübergabe, so wie To das bereits gemacht hat. Damit wird in jedem Fall das richtige Quoting Zeichen genommen, da unterschiedliche SQL Server verschiedene Zeichen nutzen macht Zeos das dann richtig.
Bei dem Parameter :Suche1 ist es wichtig dass vor dem : und am Ende ein Leerzeichen steht, damit decodiert das Zeos richtig.

Code: Alles auswählen

 
: :
     SQL.Add('WHERE (UPPER(rText) LIKE :Such1 Or UPPER(rTitel) LIKE :Such1 Or UPPER(rHinweis) LIKE :Such1 )');
: :
     Params.ParamValues['Such1'] := UpperCase(sss);
: :
 
EleLa - Elektronik Lagerverwaltung - www.elela.de

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Soner »

Ich kenne die Lösung deines Problems nicht, aber ich kann dir zwei Tipps zu Sqlite geben.
Ich verwende bei der Sortierung:
ORDER BY rTitel COLLATE NOCASE
und nicht
ORDER BY UPPER(rTitel)

Das Erste vergleicht maximal 26 Zeichen aber UPPER wandelt erst alle in Großbuchstaben dann vergleichts es. UPPER ist das altes Verfahren von BDE.

Man kann es auch gleich bei der Tabellenerstellung angeben:

Code: Alles auswählen

 
CREATE TABLE XYZ(
'rTitel ' CHAR DEFAULT '' COLLATE NOCASE
);
 


Bei Firebird datenbanken geht es auch so mit COLLATE UNICODE_CI:

Code: Alles auswählen

 
CREATE TABLE XYZ(
rTitel VARCHAR(50) CHARACTER SET UTF8 COLLATE UNICODE_CI ,
);
 


Näheres für Sqlite kannst du hier lesen:
https://www.sqlite.org/datatype3.html

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

[gelöst] Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Aliobaba »

Vielen herzlichen Dank!
Der Tip von MmVisual brachte die Lösung!
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Aliobaba »

Hallo,

da habe ich mich nun leider zu früh gefreut:

Code: Alles auswählen

Procedure Texte_zu_Wort_suchen (sss : string ; flag : integer)// 0:Mitte 1: am Anfang 2: am Ende
begin
    if flag = 0 then   sss := '%' + sss + '%';
    if flag = 1 then   sss := sss + '%';
    if flag = 2 then   sss := '%' + sss ;
 
   Form2.Edit1.Text:=sss; // zur Kontrolle des Inhalts der Variable
   With form1.Qtext do
   Begin
      SQL.Clear;
      SQL.Add('SELECT * FROM tText');
      SQL.Add('WHERE (UPPER(rText) LIKE :Such1 Or UPPER(rTitel) LIKE :Such1 Or UPPER(rHinweis) LIKE :Such1 )');
      SQL.Add('ORDER BY UPPER(rTitel)');
      Params.ParamValues['Such1'] := UpperCase(sss);
      Open;
   end;
end;

funktioniert leider doch nicht! :( :?:
Wenn das Suchwort "Werb" [:=sss] verwendet wird, dann wird der Text, der das Wort "Werbung" enthält, nur mit Flag:=0 gefunden.
Eigentlich müsste doch der Text mit dem Wort: "Werbung" bei Verwendung des Flags "1" auch gefunden werden!?
In Edit1.text steht korrekt %Werb% [Flag = 0] bzw Werb% [Flag = 1]

@eb: Ich muss(!) mit Parameter arbeiten. Bei der direkten Eingabe des SQL-Statement in einen SQL-Editor (SQLite-Manager) funktioniert alles korrekt.
@Soner: Die Struktur meiner Datenbank traue ich mir nicht zu ändern; ich erwarte mir davon auch nichts, da der reine SQL-Befehl via SQL-Editor ja funktioniert wie er soll.

Aliobaba

Nachtrag:
Auch das bringt nichts:

Code: Alles auswählen

Procedure Texte_zu_Wort_suchen (sss : string ; flag : integer)// 0:Mitte 1: am Anfang 2: am Ende
begin
//    if flag = 0 then   sss := '%' + sss + '%';
//    if flag = 1 then   sss := sss + '%';
//    if flag = 2 then   sss := '%' + sss ;
   Form2.Edit1.Text:=sss; // zur Kontrolle des Inhalts der Variable
   With form1.Qtext do
   Begin
      SQL.Clear;
      SQL.Add('SELECT * FROM tText');
      SQL.Add('WHERE (UPPER(rText) LIKE :Such1 Or UPPER(rTitel) LIKE :Such1 Or UPPER(rHinweis) LIKE :Such1 )');
      SQL.Add('ORDER BY UPPER(rTitel)');
      if flag = 0 then Params.ParamValues['Such1'] := '%' + sss + '%';
      if flag = 1 then Params.ParamValues['Such1'] := sss + '%';
      if flag = 2 then Params.ParamValues['Such1'] := '%' + sss ;
      Open;
   end;             
end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von af0815 »

Aliobaba hat geschrieben:@eb: Ich muss(!) mit Parameter arbeiten. Bei der direkten Eingabe des SQL-Statement in einen SQL-Editor (SQLite-Manager) funktioniert alles korrekt.
@Soner: Die Struktur meiner Datenbank traue ich mir nicht zu ändern; ich erwarte mir davon auch nichts, da der reine SQL-Befehl via SQL-Editor ja funktioniert wie er soll.

Aliobaba


Und wenn das Statement, genauso wie SQL-Editor eingibst, geht es dann unter Lazarus ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Eb
Lazarusforum e. V.
Beiträge: 238
Registriert: Di 5. Feb 2008, 15:32
OS, Lazarus, FPC: Linux Mint - Laz 2.2.0
CPU-Target: 64Bit
Wohnort: Stuttgart

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Eb »

Ich verstehe, dass du mit Parametern arbeiten musst und möchte dich auch nicht davon abbringen.
Aber ich würde trotzdem den Versuch machen, ob es ohne Parameter geht.
Falls dies der Fall ist, würde ich mich näher mit den Parametern beschäftigen.

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von wp_xyz »

Nur so ne Idee: Hast du statt "%" schon mal einen anderen Platzhalter, z.B. "*", probiert?

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: SQL: Suche mit Like geht nur "zum Teil"

Beitrag von Aliobaba »

Hallo,

Soo; jetzt bin ich selber drauf gekommen :) Vielleicht hat jemand irgendwann ähnliche Probleme, so dass dies helfen könnte:
Der Knackpunkt: Das gesuchte Wort ist innerhalb eines Memo-Feldes!! Wenn man also nach dem Wort sucht und man möchte zusätzlich differenzieren, ob das Wort ein zusammengesetztes Wort ist und ob diese "Zusammensetzung" vorne am Wort steht oder hinten dran hängt, dann war meine Abfrage natürlich falsch: Die Suchanfrage behandelt ja den GESAMTEN Memo-Text als ein einziges zusmmenhängendes Wort!! So eine Ausdruck: 'sss + %' findet das Wort ja nur, wenn es GANZ AM ANFANG des Memo-Textes steht. :shock: :?
Tja: eigentlich ganz logisch!!

Die Suche nach einem Wort mit dem Kriterium "Steht bei einem zusammenhängenden Wort der "Zusatz" am Anfang oder am Ende" wird damit aber natürlich nicht einfacher, da alle möglichen Satzzeichen beachtet werden müßten. Ich glaube, ich lasse das lieber 8)


Danke an Alle!
Aliobaba

So jedenfalls funktioniert es, wenn vor und hinter dem Wort ein Leerzeichen steht:

Code: Alles auswählen

Procedure Texte_zu_Wort_suchen (sss : string ; flag : integer)// 0:Mitte 1: am Anfang 2: am Ende
begin
    if flag = 0 then   sss := ('%' + sss + '%');
    if flag = 1 then   sss := ('% ' + sss + '%')// man beachte das Leerzeichen!
    if flag = 2 then   sss := ('%' + sss + ' %')// man beachte das Leerzeichen!
    Form2.Edit1.Text:= sss ;  // zur Kontrolle der Eingabe
 
    With form1.Qtext do
    Begin
      SQL.Clear;
      SQL.Add('SELECT * FROM tText')
      SQL.Add('WHERE rText LIKE :Such1 Or rTitel LIKE :Such1 Or rHinweis LIKE :Such1 ');
      SQL.Add('ORDER BY rTitel');
      Params.ParamValues['Such1'] :=  sss ;
      Open;
    end;                     
end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Antworten