Suche in MySQL-Datenbank mit arrays und patterns mit spezifischen Ausnahmen

Hi!
Ich habe von einem Bekannten ein Skript für die Suche in einer MySQL-Datenbank übernommen. Dieses sucht mit arrays und patterns.
Eine Spalte der Datenbanktabelle trägt den Namen „ZG“, das dazugehörige Formulareingabefeld heißt „zugg“.
Nun ist mir allerdings aufgefallen daß die Wahl des Patterns „LIKE“ ungünstig ist, da dann bei einer suche in „ZG“ nach z.B. „E“ alle Einträge aufgelistet werden, die ein „E“ enthalten (muss ja so sein). Ich möchte allerdings nur die Einträge angezeigt bekommen welche wirklich nur aus dem „E“ bestehen.
Also muss in der foreach-Schleife wohl eine Ausnahme rein, die das neue Pattern (das müsste dann ja „=“ sein, oder?) festlegt. Allerdings weiß ich nicht, wie ich dies realisieren kann. Bei meinen bisherigen Versuchen landete ich immer wieder bei der Fehlermeldung „Bitte mindestens einen Suchbegriff eingeben“.

Hier der bisherige Code mit meinem Lösungsversuch (der nicht funktioniert hat):
values (Datenbank)
 ‚datum‘ => ‚Datum‘,
    ‚tfznr‘ => ‚Triebfahrzeug‘,
    ‚tfzevu‘ => ‚EVU‘,
    ‚tfzfarbe‘ => ‚Farbe‘,
    ‚tfzname‘ => ‚Taufname‘,
    ‚tfzmerkmal‘ => ‚Werbung‘,
    ‚tfztraktion‘ => ‚Traktion‘, 
    ‚zugnr‘ => ‚ZN‘,
    ‚zugn‘ => ‚Zugname‘,
    ‚zugstart‘ => ‚Start‘,
    ‚zugziel‘ => ‚Ziel‘,
    ‚anmerkungen‘ => ‚Anmerkungen‘,
); if(strlen($_POST[‚datum‘]) == 4) {
    $datum = $suche1;
   // echo "Neues Datum ist ".$datum;
 } else {
    $datum2 = $_POST[‚datum‘];
       $umbau = strtotime($datum2);
       //echo $umbau;
       $datum = date(‚Y-m-d‘, $umbau);
    //echo "Datum ist ".$datum;
   }/*$datum2 = $_POST[‚datum‘];
$umbau = date_create_from_format(‚j-M-Y‘,$datum2);
echo $umbau;
$datum = date($umbau,‚Y-m-d‘);
echo "Datum ist ".$datum;*//*$datum2 = $_POST[‚datum‘];
$umbau = DateTime::createFromFormat(‚Y-M-j‘, $datum2);
$datum = $date->format(‚d.m.Y‘); */
// Jede Teilabfrage lautet LIKE ‚% … %‘, aber vielleicht will man das ja mal ändern… 
// Wird sprintf() benutzt, müssen Prozentzeichen doppelt geschrieben werden, um sie in den resultierenden String zu bekommen
$sqlPattern = „%s LIKE ‚%%%s%%‘“;
// Teilabfragen in Array ablegen, hier: array initialisieren
$conditions = array();
// Sicherstellen, dass alle Felder berücksichtigt werden (jedes Feld könnte vorkommen)
foreach ($mapPOST2DB as $keyPOST => $keyDB) {
    $_POST[‚datum‘] = $datum;
 if($_POST[‚datum‘] === „1970-01-01“) {
    $_POST[‚datum‘] = „“;
    } // Gibt es den Schlüssel im POST?
    if (isset($_POST[$keyPOST]) && ($_POST[$keyPOST]) != „“)) {
        // Wert ist vorhanden, baue eine Teilabfrage und lege sie ins Array.
  $conditions[] = sprintf($sqlPattern, $keyDB, mysqli_real_escape_string($verbindung, $_POST[$keyPOST])); 
    } else {} 
/*  if (isset($_POST[‚zugg‘])) {
  $sqlPattern = „%s = ‚%%%s%%‘“;
  $conditions[] = sprintf($sqlPattern, $keyDB, mysqli_real_escape_string($verbindung, $_POST[$keyPOST])); 
 } else {}*/
 
}//Prüfen, ob mindestens ein Feld ausgefüllt wurde. Falls nein -> $conditions leer, $test = 0 Abbruch
$test = count($conditions);
if($test ';
     print $res;
     print ‚‘;*/
  //trigger_error('Datenbankanfrage schlug fehl: '.mysqli_error(), E_USER_ERROR);
   }
   if(mysqli_num_rows($res) === 500) {
   echo "Es wird nur eine Auswahl an Datensätzen angezeigt, da mehr als 500 zutreffende Einträge vorhanden sind. Bitte verfeinern Sie ggf. Ihre Suche durch Eingabe zusätzlicher oder anderer Kriterien.
";
   }   
   if(mysqli_num_rows($res) > 0) {                           //Datensätze wurden gefunden; Ausgabe
     $zeilen = mysqli_num_rows($res);
  $spalten = mysqli_fetch_fields($res);
  echo "Es wurden $zeilen Datensätze zu Ihrer Suchanfrage gefunden.

„;
  echo „“;
  echo „\n“;
  echo „Datum“;
  echo „Triebfahrzeug“;
  echo „EVU“;
  echo „Farbe“;
  echo „Taufname“;
  echo „Werbung“;
  echo „Traktion“;
  echo „ZG“;
  echo „ZN“;
  echo „Zugname“;
  echo „Start“;
  echo „Ziel“;
  echo „Anmerkungen“;
  while($row = mysqli_fetch_assoc($res)):
  echo ‚‘.“\r\n";
     echo ‚‘.$row[‚Datum‘].’’."\r\n";
  echo ‚‘.$row[‚Triebfahrzeug‘].’’."\r\n";
  echo ‚‘.$row[‚EVU‘].’’."\r\n";
  echo ‚‘.$row[‚Farbe‘].’’."\r\n";
  echo ‚‘.$row[‚Taufname‘].’’."\r\n";
  echo ‚‘.$row[‚Werbung‘].’’."\r\n";
  echo ‚‘.$row[‚Traktion‘].’’."\r\n";
  echo ‚‘.$row[‚ZG‘].’’."\r\n";
  echo ‚‘.$row[‚ZN‘].’’."\r\n";
  echo ‚‘.$row[‚Zugname‘].’’."\r\n";
  echo ‚‘.$row[‚Start‘].’’."\r\n";
  echo ‚‘.$row[‚Ziel‘].’’."\r\n";
  echo ‚‘.$row[‚Anmerkungen‘].’’."\r\n";
  echo ‚‘."\r\n";
  $i++;                                          //Zähler für dynamischen Tabellenaufbau fortsetzen
    /*echo $row[‚Datum‘];
       echo $row[‚Triebfahrzeug‘];
    echo $row[‚EVU‘];
    echo $row[‚Farbe‘];
       echo $row[‚Taufname‘];
       echo $row[‚Werbung‘];
       echo $row[‚Traktion‘];
       echo $row[‚ZG‘];
       echo $row[‚ZN‘];
       echo $row[‚Zugname‘];
       echo $row[‚Start‘];
    echo $row[‚Ziel‘];
    echo $row[‚Anmerkungen‘];*/
  endwhile;
  echo „\n“;
   } 
?>

das ganze scheint mir etwas unnötig kompliziert zu sein.
Versuch doch bitte mal ne eigene Konstruktion zu schreiben mit der Möglichkeit auf entweder SELECT * FROM Tabelle WHERE Feld = ‚E‘  … oder
WHERE Feld LIKE ‚E‘  (ohne die „%“)

und schau dir von dem Script nur das Nötigste ab.
diese ganzen mysqli_real_escape_string sind ja nur dazu da ungültige, bzw. Hacker-Eingaben zu escapen.
Ich möchte mal behaupten dass in dem Script viel überflüssiges Zeugs drin ist.

Vielleicht ist es auch besser wenn du die INSERTS / UPDATES für das Array und die Posts nacheinander machst und sie nicht vermischt. Dann könntest du auch einen extra SQL abschicken für Sonderabfragen.

statt
if ($_POST[$keyPOST]) != „“)
kannst du auch einfach schreiben: if ($_POST[$keyPOST]))

Ich würde vorschlagen, den Code so weit wie möglich zu verschlanken und dann peu a peu etwas mehr Funktionalität reinzunehmen - das übliche Coden und Debuggen eben.

Ansonsten läufst Du genau in diese Probleme rein - also ran an den Feind und noch einmal selbst nachbauen - so mache ich das jedenfalls immer bei „fremden“ Code…

Hallo elixir,

im Grunde wurde es im Code bereits angedeutet:

// Jede Teilabfrage lautet LIKE ‚% … %‘, aber vielleicht will man das ja mal ändern… 

Es ist also eher anders herum als du es verstanden zu haben scheinst:
„Like“ IST ein „genau gleich“. Würdest du " where zg like ‚e‘ " schreiben, würden die Worte „es“ oder „sie“ nicht getroffen werden.
Allerdings wird in deinem Code automatisch % davor und dahinter hinzugefügt.
% ist dabei ein Platzhalter für beliebig viele Zeichen an dieser Stelle.

Nun ist die Frage, ob du ALLE suchanfragen, also alle Spalten, auf GENAU-GLEICH abfragen möchtest, oder nur ZG.
Im ersten Fall entfernst du einfach die %% :
$sqlPattern = „%s LIKE ‚%%%s%%‘“;
wird zu
$sqlPattern = „%s LIKE ‚%s‘“;

Willst du nur ZG verändern, wirst du das wohl über einen IF-zweig abfragen müssen, ob es um das zugg-Feld geht und dann die %% weglassen.

mit freundlichen Grüßen
Julian

so etwas umgeschrieben
und deine ‚zugg‘ abfrage dahin gepackt
wo sie sinn macht (in die ist nicht leer feld abfrage mit rein)

<?php $debug = true;
//Verbindungsdaten für Datenbank $db=array("host"=\>"\*","user"=\>"\*","pass"=\>"\*","name"=\>"\*"); //Herstellen der Verbindung $verbindung = mysqli\_connect($db["host"], $db["user"], $db["pass"], $db["name"]); //Zeichensatz anpassen mysqli\_query($verbindung,"SET NAMES 'utf8'"); mysqli\_query($verbindung,"SET CHARACTER SET 'utf8'"); if(!$verbindung) { exit("Es konnte keine Verbindung zur Datenbank hergestellt werden. Bitte versuchen Sie es zu einem späteren Zeitpunkt erneut."); } /\* Einlesen der Suchparameter \* (wird nur benötigt für Ausgabe der Suchkriterien auf Ergebnisseite; \* bei Inaktivität werden die Suchbegriffe nicht auf Ergebnisseite angezeigt.) \*/ // POST escapen $mapPOST2DB = array( //keys (Formular) =\> values (Datenbank) 'datum' =\> 'Datum', 'tfznr' =\> 'Triebfahrzeug', 'tfzevu' =\> 'EVU', 'tfzfarbe' =\> 'Farbe', 'tfzname' =\> 'Taufname', 'tfzmerkmal' =\> 'Werbung', 'tfztraktion' =\> 'Traktion', 'zugnr' =\> 'ZN', 'zugn' =\> 'Zugname', 'zugstart' =\> 'Start', 'zugziel' =\> 'Ziel', 'anmerkungen' =\> 'Anmerkungen', ); // escape suchfelder $suche = array(); // post map escape foreach($mapPOST2DB as $sfeld =\> $swert) { $suche[$sfeld] = mysqli\_real\_escape\_string($verbindung,$\_POST[$sfeld]); } //Zusammenstellen der Suchanfrage if(strlen($suche['datum']) == 4) { $datum = $suche['datum']; if ($debug) echo "Neues Datum ist ".$datum; } else { $datum2 = $suche['datum']; $umbau = strtotime($datum2); if ($debug) echo $umbau; $datum = date('Y-m-d', $umbau); } // Jede Teilabfrage lautet LIKE '% ... %', aber vielleicht will man das ja mal ändern... // Wird sprintf() benutzt, müssen Prozentzeichen doppelt geschrieben werden, um sie in den resultierenden String zu bekommen $sqlPattern = "%s LIKE '%%%s%%'"; // Teilabfragen in Array ablegen, hier: array initialisieren $conditions = array(); // Sicherstellen, dass alle Felder berücksichtigt werden (jedes Feld könnte vorkommen) foreach ($mapPOST2DB as $keyPOST =\> $keyDB) { $suche['datum'] = $datum; if($suche['datum'] === "1970-01-01") { $suche['datum'] = ""; } // Gibt es den Schlüssel im POST? if ($suche[$keyPOST] != "") { if ($keyPOST == 'zugg') { // nur beim 'zugg' feld $sqlPattern = "%s = '%%%s%%'"; $conditions[] = sprintf($sqlPattern, $keyDB, $suche[$keyPOST]); } else { // Wert ist vorhanden, baue eine Teilabfrage und lege sie ins Array. $conditions[] = sprintf($sqlPattern, $keyDB, $suche[$keyPOST]); } } } // Prüfen, ob mindestens ein Feld ausgefüllt wurde. Falls nein -\> $conditions leer, $test = 0 Abbruch $test = count($conditions); if($test '; print $res; print ''; \*/ // trigger\_error('Datenbankanfrage schlug fehl: '.mysqli\_error(), E\_USER\_ERROR); } if(mysqli\_num\_rows($res) === 500) { echo "Es wird nur eine Auswahl an Datensätzen angezeigt, da mehr als 500 zutreffende Einträge vorhanden sind. Bitte verfeinern Sie ggf. Ihre Suche durch Eingabe zusätzlicher oder anderer Kriterien. "; } if(mysqli\_num\_rows($res) \> 0) { //Datensätze wurden gefunden; Ausgabe $zeilen = mysqli\_num\_rows($res); $spalten = mysqli\_fetch\_fields($res); $ausgabe = "Es wurden $zeilen Datensätze zu Ihrer Suchanfrage gefunden. "; $ausgabe = Datum Triebfahrzeug EVU Farbe Taufname Werbung Traktion; ZG ZN Zugname Start Ziel Anmerkungen HEADOUTPUT; while($row = mysqli\_fetch\_assoc($res)) { $ausgabe .=''."\r\n"; $ausgabe .=$row[Datum] $row[Triebfahrzeug] $row[EVU] $row[Farbe] $row[Taufname] $row[Werbung] $row[Traktion] $row[ZG] $row[ZN] $row[Zugname] $row[Start] $row[Ziel] $row[Anmerkungen] ENTRYOUTPUT; //Zähler für dynamischen Tabellenaufbau fortsetzen $i++; } $ausgabe .= "\n"; echo $ausgabe; } ?\>

Hey,

du solltest wirklich den Code vereinfachen und für deine Testphase diese ganzen Sicherheitsfunktionen weg lassen. Wenn dein Script mal die gewüschte Funktion hat, kannst du sie ja wieder einbauen.

Zu deinem eigentlichen Probem kann ich mich meinen Vorrednern nur anschließen.

Hi,

statt
if ($_POST[$keyPOST]) != „“)
kannst du auch einfach schreiben: if ($_POST[$keyPOST]))

korrekt wäre:

 if(isset($\_POST['key'])

und wenn man pedantisch ist wäre der korrekte Weg:

 if(isset($\_POST['key'] && $\_POST['key'] == 'irgendwas')

Gruß XXD

Hi!
Zuerst mal danke für die Antworten !
Ich habe den Code jetzt umgeschrieben und die Vorschläge aus den Antwortbeiträgen eingebaut allerdings funktioniert die Suche noch nicht richtig.
Wenn ich jetzt nach „E“ im Feld „ZG“ suche kommt die Meldung , daß keine Datensätze gefunden wurden, obwohl welche existieren. Das hier ist der Text meiner Abfrage:
$suche = array();
//post map escapen
foreach($mapPOST2DB as $keyPOST => $keyDB) {
$suche[$keyPOST] = mysqli_real_escape_string($verbindung,$_POST[$keyPOST]);
}

if(strlen($_POST[‚datum‘]) == 4) {
$datum = $suche1;
// echo "Neues Datum ist ".$datum;
} else {
$datum2 = $_POST[‚datum‘];
$umbau = strtotime($datum2);
//echo $umbau;
$datum = date(‚Y-m-d‘, $umbau);
//echo "Datum ist ".$datum;
}
//…
$sqlPattern = „%s LIKE ‚%%%s%%‘“;
// Teilabfragen in Array ablegen, hier: array initialisieren
$conditions = array();
// Sicherstellen, dass alle Felder berücksichtigt werden (jedes Feld könnte vorkommen)
foreach ($mapPOST2DB as $keyPOST => $keyDB) {
$suche[‚datum‘] = $datum;
if($suche[‚datum‘] === „1970-01-01“) {
$suche[‚datum‘] = „“;
}

// Gibt es den Schlüssel im POST?
if ($suche[$keyPOST] != „“) {
if ($keyPOST == ‚zugg‘) {
$sqlPattern = „%s = ‚%%%s%%‘“;
$conditions[] = sprintf($sqlPattern, $keyDB, $suche[$keyPOST]);
} else {
$conditions[] = sprintf($sqlPattern, $keyDB, $suche[$keyPOST]);
}
}

die Ausgabe erfolgt über

$ergebnis = „SELECT DATE_FORMAT(Datum,’%d.%m.%Y’) AS „.implode(“,“,$mapPOST2DB)." FROM zugdatenbank WHERE $where LIMIT 500";

Ich sehe im Augenblick nicht wo bei mir der Fehler liegt . Der Code an sich scheint ja zu funktionieren, nur aus irgendeinem Grund kommt ein leeres Resultat zurück.