2016-03-24 11 views
0

Ich muss eine Delphi 7 und MySQL Datenbankabfrage schreiben, die die Datensätze einschließlich aller Wörter im übermittelten Namen zurückgeben würde. Die Abfrage wird also Datensätze zurückgeben, die all diese Namen enthalten, aber unterschiedliche Reihenfolge haben können.Abfrage zu Suche Alle möglichen Wörter

Zum Beispiel, wenn die Suchzeichenfolge John Michael Smith ist, sollte Abfrage in der Lage sein, Datensätze mit Namen wie John Smith Michael, Michael Smith John, Smith John Michael oder andere Kombination mit all diesen Wörtern dort zurückzugeben.

Wie zu sehen gibt nur Datensätze zurück, die noch alle Wörter im Namensfeld haben, aber unterschiedliche Reihenfolge haben können. Ich kann nicht herausfinden, wie man eine Abfrage für eine solche Anforderung schreiben, die ich habe. Bitte helfen Sie.

procedure Tfrm_Query.Button1Click(Sender: TObject); 
var 
mask : string; 
begin 
    mask:='''%'+StringReplace(Edit1.text,' ','%',[rfReplaceAll, rfIgnoreCase])+'%'''; 
    if Edit1.Text > '' then 
    begin 
    Adosorgulama.Close; 
    Adosorgulama.SQL.Clear; 
    Adosorgulama.SQL.Add('SELECT * FROM stok.product'); 
    Adosorgulama.SQL.ADD('Where (P_Name like '+mask+') limit 50'); 
    Adosorgulama.Open; 
end; 
end; 

als Ergebnis;

edit1.text:='Jo Mich'; // Result Ok! 
edit1.text:='Smi Jo Mic'; //No result 
edit1.text:='Mich Sm'; // No result 
+0

Sie haben vergessen, alle Informationen, die das DBMS in Bezug auf die Sie verwenden, um die Komponenten Sie verwenden die Daten zuzugreifen, werden alle Informationen in Bezug auf Ihre Tabellenstruktur oder keine Informationen über die SQL-Anweisung Sie haben versucht zu erstellen. Kannst du [bearbeiten], um diese Details aufzunehmen? Vielen Dank. –

Antwort

0

Statt ersetzen Räume mit %, könnten Sie ersetzen sie durch % AND P_Name LIKE %:

mask:='''WHERE (P_Name LIKE %'+StringReplace(Edit1.text,' ','% AND P_Name LIKE %',[rfReplaceAll, rfIgnoreCase])+'%)'''; 

Entschuldigt, wenn es irgendein Problem mit der Syntax ist (ich weiß Delphi nicht), aber wenn Edit1.text:= 'John Michael Smith' soll dies die folgende Klausel WHERE erzeugen:

WHERE (P_Name LIKE %John% AND P_Name LIKE %Michael% AND P_Name LIKE %Smith%) 

Das sollte alle Datensätze finden, in denen P_Name die Zeichenfolgen "John", "Michael" und "Smith" enthält.

Dann natürlich, statt

Adosorgulama.SQL.ADD('Where (P_Name like '+mask+') limit 50'); 

Sie so etwas wie

Adosorgulama.SQL.ADD(mask + ' limit 50'); 

tun würde, wenn die Eingangsfremd Leerzeichen enthalten können, müssen Sie diese zuerst, sonst diese gewonnen entfernen arbeite nicht.

Das Erstellen von SQL-Abfragen mit String-Verkettung könnte Ihre Anwendung anfällig für SQL-Injection machen, nur damit Sie es wissen. Ich weiß nicht, wie man vorbereitete Aussagen mit Delphi macht, also kann ich dir nicht helfen.

0

Schreiben Sie eine Funktion, die den Namen nach Leerzeichen aufteilen kann. Verwenden Sie den folgenden Code in einer Schleife, die Split-Ergebnisse enthält.

Declare @sqlq as nvarchar(max); 

-- loop start 
@sqlq = sqlq + 'Select * from mytable where names'; 

@sqlq = sqlq + 'like ''%' + loopvalue + '%'''; 
--loop end 

Exec @sqlq 
+0

Ich denke, du hast die Frage bearbeitet. Aber Sie können dieselbe Logik auf mysql mit einer etwas anderen Syntax verwenden. – osmanraifgunes

0

Sie können die Worttabelle dynamisch erstellen. Um Ihnen Abfrage tun übereinstimmen, die beide Tabellen in mögliche Übereinstimmung kommen, und durch die Gruppierung Ergebnisse testen - ist der Name alle Wörter haben, versuchen Sie dies:

WITH 
    words AS (SELECT 'John' AS word FROM dual union 
     SELECT 'Michael' FROM dual union 
     SELECT 'Smith' FROM dual) , --build your table of words (this is example on oracle DB engine) 
    names AS (SELECT 'John Michael Smith' AS name FROM dual UNION 
     SELECT 'John SmithMichael' FROM dual union 
     SELECT 'Smith Michael' FROM dual union 
     SELECT 'Smith Michael John' FROM dual union 
     SELECT 'John' FROM dual union 
     SELECT 'John John' FROM dual union 
     SELECT 'John John John' FROM dual union 
     SELECT 'xyz abc' FROM dual) --this is simulation of yours table of names  
SELECT name, Count(DISTINCT word) 
FROM names, words 
WHERE ' ' || name || ' ' LIKE '% ' || word || ' %' 
GROUP BY name 
HAVING Count(DISTINCT word) = (SELECT Count(1) FROM words) 
; 
0

Problem ist gelöst. Delphi + MySQL-Verbindung mit Wortreihenfolge mit dem folgenden Code, unabhängig von Anrufen vorgenommen werden kann. Danke für die Inspiration. Respekt.

Datenbankmodell;

CREATE TABLE IF NOT EXISTS `TableName` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `PNUMBER` varchar(20) DEFAULT NULL, 
    `PNAME` varchar(255) DEFAULT NULL, 
    `PBARCODE` varchar(30) DEFAULT NULL, 
    `PSearch` mediumtext, 
    PRIMARY KEY (`ID`), 
    FULLTEXT KEY `PSearch` (`PSearch`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin5 ; 

Psuche = PNUMBER + PNAME + PBARCODE ...; (Geben Sie alle Bereiche ein PSearch)

Delphi7 Code;

procedure TForm1.Button1Click(Sender: TObject); 
var 
mask : string; 
begin 
mask:='+'+StringReplace(Edit1.text,' ','* +',[rfReplaceAll, rfIgnoreCase])+'*'; 
if Edit1.Text > '' then 
begin 
    Query1.Close; 
    Query1.SQL.Clear; 
    Query1.SQL.Add('SELECT MATCH(PSearch) AGAINST("'+mask+'" IN BOOLEAN MODE), tablename.* FROM database.tablename'); 
    Query1.SQL.Add('WHERE MATCH(PSearch) AGAINST("'+mask+'" IN BOOLEAN MODE) limit 300;'); 
    Query1.Open; 
    end; end; 
Verwandte Themen