Leere Felder bei Datenabfrage aussparen
alexsus
- php
Hallo zusammen,
ich habe ein Abfrageformular bei dem der Nutzer nicht alle Felder ausfüllen muss, aber kann! Nun habe ich aber das Problem wenn ich alle Felder aus der Datenbank abragen möchte werden auch die Felder abgefragt die leer sind.
Hier mal der Quelltext und ein kurzes Beispiel:
$ergebnis=mysql_query ("select * from hersteller where betriebssystem='$betriebssystem' and typ='$typ' and hersteller='$hersteller'");
while ($datensatz=mysql_fetch_row($ergebnis))
Wenn der Nutzer nur die Felder Betriebssystem und Typ ausfüllt und Hersteller leer bleibt wird trotzdem in der Datenbank nach einm Datensatz gesucht bei dem alle 3 Felder übereinstimmen - es wird also ein Datensatz gesucht bei dem das Feld Hersteller leer ist!!!
Wie kann ich das umgehen, sodass alle Datensätze ausgegeben werden wo die Betriebssystem und Typ übereinstimmen, aber das Feld Hersteller ausgespart wird?
Mfg Alex
Einfachste Lösung: In den sauren Apfel beißen und für jedes Feld eine IF-Abfrage, ob das Formular-Feld einen Wert enthält..
Einfachste Lösung: In den sauren Apfel beißen und für jedes Feld eine IF-Abfrage, ob das Formular-Feld einen Wert enthält..
If-Anweisung so wie seppel beschrieben hat oder hast du eine andere Lösung / Lösungsansatz?
Mfg Alex
hi,
$ergebnis=mysql_query ("select * from hersteller where betriebssystem='$betriebssystem' and typ='$typ' and hersteller='$hersteller'");
while ($datensatz=mysql_fetch_row($ergebnis))
Ich würde mir die Restriction einfach vor dem Aufruf zusammenstellen - in etwa so:
If $betriebssystem <> "" Then
myrestriction = myrestriction & " and betriebssystem = '" & $betriebssystem & "'"
End If
If $typ <> "" Then
myrestriction = myrestriction & " and typ = '" & $typ & "'"
End If
If $hersteller <> "" Then
myrestriction = myrestriction & " and hersteller = '" & $hersteller & "'"
End If
$ergebnis=mysql_query ("select * from hersteller where 1=1" & myrestriction);
Oder so in der Art halt...
Gruss,
Seppel
Das ist aber keine PHP-Syntax... :)
Das ist aber keine PHP-Syntax... :)
erwischt! aber das sollte der Fragesteller schnell umgebastelt haben - ich muss mich leider mit ASP, also VBScript, rumschlagen...ABER ich hab die Variablen mit $ versehen ;-)
hi,
$ergebnis=mysql_query ("select * from hersteller where betriebssystem='$betriebssystem' and typ='$typ' and hersteller='$hersteller'");
while ($datensatz=mysql_fetch_row($ergebnis))Ich würde mir die Restriction einfach vor dem Aufruf zusammenstellen - in etwa so:
If $betriebssystem <> "" Then
myrestriction = myrestriction & " and betriebssystem = '" &
....
Der Ansatz sieht richtig gut aus. Kannst mir auch noch in Tipp geben wie ich die unmengen von Klammern da setzen muß?
Mfg Alex
hola,
Der Ansatz sieht richtig gut aus. Kannst mir auch noch in Tipp geben wie ich die unmengen von Klammern da setzen muß?
Mfg Alex
was für Klammern - sind doch mit "and" verknüpft die Bedingungen - da brauchst du keine Klammern.
Oder was meinst du genau?
was für Klammern - sind doch mit "and" verknüpft die Bedingungen - da brauchst du keine Klammern.
Oder was meinst du genau?
Naja in einer if-Anweisung brauchst doch auch Klammern so nach dem Schema:
if (Bedingung)
{ } //In den geschweiften steht die Anweisung
else //wenn if nicht zutrifft
{ } //In den geschweiften steht die Anweisung
Mfg
if (Bedingung)
{ } //In den geschweiften steht die Anweisung
else //wenn if nicht zutrifft
{ } //In den geschweiften steht die Anweisung
ok, verstehe was du meinst - würde hier aber auf jeden Fall auf "else" verzichten, da du ja jegliche Konstallation erwischen willst. Der User könnte ja auch nur das letzte Attribut eingeben.
D.h. du fragst einfach jedes einzeln in einer if (Bedingung) {res = res + " ... "} ab.
Gruss,
Seppel
ok, verstehe was du meinst - würde hier aber auf jeden Fall auf "else" verzichten, da du ja jegliche Konstallation erwischen willst. Der User könnte ja auch nur das letzte Attribut eingeben.
D.h. du fragst einfach jedes einzeln in einer if (Bedingung) {res = res + " ... "} ab.
Also dan quasi so ?
If ($betriebssystem <> "")
Then {myrestriction = myrestriction & " and betriebssystem = '" & $betriebssystem & "'"}
End If
If ($typ <> "")
Then {myrestriction = myrestriction & " and typ = '" & $typ & "'"}
End If
If ($hersteller <> "")
Then {myrestriction = myrestriction & " and hersteller = '" & $hersteller & "'"}
End If
$ergebnis=mysql_query ("select * from hersteller where 1=1" & myrestriction);
If ($betriebssystem <> "")
Then {myrestriction = myrestriction & " and betriebssystem = '" & $betriebssystem & "'"}
End If
If ($typ <> "")
Then {myrestriction = myrestriction & " and typ = '" & $typ & "'"}
End If
If ($hersteller <> "")
Then {myrestriction = myrestriction & " and hersteller = '" & $hersteller & "'"}
End If
$ergebnis=mysql_query ("select * from hersteller where 1=1" & myrestriction);
ESCAPING REINMACHEN!!! mysql_real_escape_string() existiert nicht zum Spaß.
ESCAPING REINMACHEN!!! mysql_real_escape_string() existiert nicht zum Spaß.
Na dann sag mir mal mehr als nur escaping - hab deine erste antwort schon nicht verstanden. bin zugegebenermaßen nicht der php und sql profi deshalb könnten es dann schon in paar mehr worte sein als nur so ein brocken nach dem motto 'friss oder stirb' ...
echo $begrüßung;
ESCAPING REINMACHEN!!! mysql_real_escape_string() existiert nicht zum Spaß.
Na dann sag mir mal mehr als nur escaping - hab deine erste antwort schon nicht verstanden. bin zugegebenermaßen nicht der php und sql profi deshalb könnten es dann schon in paar mehr worte sein als nur so ein brocken nach dem motto 'friss oder stirb' ...
Siehe PHP-Handbuch-Kapitel SQL-Injection.
Oder allgemein gesagt: Kontextwechsel beachten - </archiv/2007/1/t144489/#m937659>
echo "$verabschiedung $name";
So hab dann mal in paar Dokus gelesen und gebastelt mit dem ergebnis das es nicht funktioniert :( Nach wie vor das gleiche Problem - wenn nix im Feld drin steht liefert die Suche kein Ergebnis.
Hier mal der Quelltext dazu vielleicht sieht ja jemand noch ne Fehler.
$ergebnis = sprintf("select * from hersteller WHERE hersteller='%s' AND typ='%s'",
mysql_real_escape_string($hersteller),
mysql_real_escape_string($typ));
echo $ergebnis; \Ausgabe des Querys
$abfrage=mysql_query ("$ergebnis");
print "<table border=1>\n";
while ($datensatz=mysql_fetch_row($abfrage))
{
print "<tr>\n";
foreach ($datensatz as $feld)
print "\t<td>$feld</td>\n";
print "</tr>\n";
}
print "</tr></table>\n";
echo $begrüßung;
So hab dann mal in paar Dokus gelesen und gebastelt mit dem ergebnis das es nicht funktioniert :( Nach wie vor das gleiche Problem - wenn nix im Feld drin steht liefert die Suche kein Ergebnis.
Du musst beides miteinander verbinden, den Aufbau des SQL-Statements in Abhängigkeit von den übergebenen Werten und beim Einfügen der Werte selbige escapen. Etwa so:
$where = array();
if (!empty(trim($eingabe1)))
$where[] = sprintf('feldname1="%s"', mysql_real_escape_string($eingabe1));
if (!empty(trim($eingabe2)))
$where[] = sprintf('feldname2="%s"', mysql_real_escape_string($eingabe2));
...
$sql = 'SELECT ... WHERE ' . implode(' AND ', $where);
echo "$verabschiedung $name";
laut
http://www.php-homepage.de/manual/function.mysql-real-escape-string.php
soll die methode die ich angewendet auch funktionieren :(
echo $begrüßung;
laut http://www.php-homepage.de/manual/function.mysql-real-escape-string.php soll die methode die ich angewendet auch funktionieren :(
Dein Problem, die gewünschte Such-Funktionalität herzustellen, ist nicht das richtige Escaping. Das musst du einsetzen, um SQL-Injection zu verhindern, und um z.B. einfache und doppelte Gänsefüße so zu kennzeichnen, dass sie nicht als Stringbegrenzung gewertet werden. Wenn du nach O'Conner suchst und den String in '' einrahmst hast du beim ' das dem O folgt ein Problem.
Aber zurück zum Thema. Du hast zwei Eingabefelder für die Suche. Eins befüllst du mit dem Wert foo, das andere lässt du leer. Wenn du nun eine Abfrage
SELECT * FROM table WHERE feld1 = 'foo' AND feld2 = ''
hast, werden natürlich nur Datensätze gefunden, bei denen sowohl foo in feld1 steht als auch einen Leerstring in feld2 haben. Wenn feld2 einen Wert ungleich Leerstring enthält, wird der Datensatz nicht gefunden. Bei AND müssen beide Bedingungen erfüllt sein.
Wenn nur eine Bedingung erfüllt sein muss, könntest du OR verwenden. Aber auch das lässt ein paar Wünsche offen. Sind beide Eingaben leer, werden nicht etwa alle Datensätze gefunden, sondern nur die, bei denen mindestens eins der beiden Felder einen Leerstring enthält. Bei feld1 = 'foo' OR feld2 = '' werden Datensätze gefunden, die foo in feld1 haben und auch solche, die einen Leerstring in feld2 haben, also (foo, ''), (foo, bal), (bar, '').
Wenn du nun leere Felder gar nicht berücksichtigen möchtest, musst du dafür sorgen, dass das SQL-Statement keine Bedingung für dieses Feld enthält. Die entsprechenden Teile dürfen also gar nicht erst in der WHERE-Klausel aufgeführt werden. Du musst also nicht nur Werte in dein Statement einfügen, sondern dir auch noch die WHERE-Klausel selbst zusammenbauen.
echo "$verabschiedung $name";
$where = array();
if (!empty(trim($eingabe1)))
$where[] = sprintf('feldname1="%s"', mysql_real_escape_string($eingabe1));
if (!empty(trim($eingabe2)))
$where[] = sprintf('feldname2="%s"', mysql_real_escape_string($eingabe2));
...
$sql = 'SELECT ... WHERE ' . implode(' AND ', $where);
Ok hab das gestern mal so ausprobiert, aber
1.) bekomme immer eine fehler angezeigt das der quelltext bei 'if (!empty(trim($eingabe1)))' fehlerhaft ist.
2.) verstehe das mit dem $where=arry(); nicht so ganz.
kannst du mir da bitte nochmal in denkanstoß geben ;)
mfg alex
echo $begrüßung;
1.) bekomme immer eine fehler angezeigt das der quelltext bei 'if (!empty(trim($eingabe1)))' fehlerhaft ist.
Stimmt, empty() möchte nur Variablen, keine Funktionsergebnisse. if (strlen(trim($eingabe1))) sollte funktionieren.
2.) verstehe das mit dem $where=array(); nicht so ganz.
Damit wird ein leeres Array der Variable $where zugewiesen. Das ist eine explizite Initialisierung der Variablen, damit sie zum einen auf jeden Fall angelegt wird und zum anderen einen definierten Wert hat. Die bedingten Anweisungen fügen ja nur Felder hinzu, wenn die Bedingung zutrifft. Sie würden dabei auch die Variable anlegen, wenn sie noch nicht existierte. Wenn keine Bedingung zutrifft existiert die Variable nicht, und der lesende Zugriff beim Aufruf von implode wäre ein Fehler. Außerdem könnte jemand die Variable unerwünscht vorbelegt haben, wenn register_globals eingeschaltet sein sollte.
echo "$verabschiedung $name";
1.) bekomme immer eine fehler angezeigt das der quelltext bei 'if (!empty(trim($eingabe1)))' fehlerhaft ist.
Stimmt, empty() möchte nur Variablen, keine Funktionsergebnisse. if (strlen(trim($eingabe1))) sollte funktionieren.
2.) verstehe das mit dem $where=array(); nicht so ganz.
Damit wird ein leeres Array der Variable $where zugewiesen. Das ist eine explizite Initialisierung der Variablen, damit sie zum einen auf jeden Fall angelegt wird und zum anderen einen definierten Wert hat.
Es funktioniert :)))
Das nenn ich doch mal sehr hilfreich vorallem mit der Erklärung dazu.
Danke
Jetzt hab ich nur noch eine Frage. Wenn ich diesen Ausdruck '$sql = 'select * from hersteller WHERE ' . implode(' AND ', $where);' für die Datenbankabfrage nutze wie kann ich dann Bedingungen einbinden - z.B. Nutzer <= 500?
MFG
echo $begrüßung;
Jetzt hab ich nur noch eine Frage. Wenn ich diesen Ausdruck '$sql = 'select * from hersteller WHERE ' . implode(' AND ', $where);' für die Datenbankabfrage nutze wie kann ich dann Bedingungen einbinden - z.B. Nutzer <= 500?
Am geschicktesten wäre es, wenn du sie bedingungslos (also ohne if) als ein weiteres Element des $where-Arrays anlegst. $where[] = 'Nutzer <= 500';. Denn in dem Fall hast du kein AND zu viel oder zu wenig, weil das implode() sich um die richtige Anzahl kümmert.
echo "$verabschiedung $name";
echo $begrüßung;
Jetzt hab ich nur noch eine Frage. Wenn ich diesen Ausdruck '$sql = 'select * from hersteller WHERE ' . implode(' AND ', $where);' für die Datenbankabfrage nutze wie kann ich dann Bedingungen einbinden - z.B. Nutzer <= 500?
Hmm müßte doch eigentlich auch mit PHP Variablen funktionieren macht es aber irgendwie nich. Habs auch schon mit '' probiert aber der zeicht mir dann immer einen Error in dem SQL Query an?!?
$where[] = 'nutzer <= $nutzer';
echo $begrüßung;
Jetzt hab ich nur noch eine Frage. Wenn ich diesen Ausdruck '$sql = 'select * from hersteller WHERE ' . implode(' AND ', $where);' für die Datenbankabfrage nutze wie kann ich dann Bedingungen einbinden - z.B. Nutzer <= 500?
Hmm müßte doch eigentlich auch mit PHP Variablen funktionieren macht es aber irgendwie nich. Habs auch schon mit '' probiert aber der zeicht mir dann immer einen Error in dem SQL Query an?!?
$where[] = 'nutzer <= $nutzer';
Hat sich erledigt - hab mich mal wieder mit den ' und " vertan :( ->
$where[] = "nutzer <= '$nutzer'";
echo $begrüßung;
$where[] = "nutzer <= '$nutzer'";
Wo kommt der Wert in $nutzer her? Hast du den selbst bereitgestellt oder stammt er aus einer nicht vertrauenswürdigen Quelle, wie Nutzereingabe oder einer Datenbank? Und bist du sicher, dass er keine Zeichen mit Sonderbedeutung enthalten kann? Verwende lieber mysql_real_escape_string(), wenn du solche Werte in MySQL-Statements (oder Teile davon) einfügen möchtest. z.B. so:
$where[] = sprintf("nutzer <= '%s'", mysql_real_escape_string($nutzer));
echo "$verabschiedung $name";
Wo kommt der Wert in $nutzer her? Hast du den selbst bereitgestellt oder stammt er aus einer nicht vertrauenswürdigen Quelle, wie Nutzereingabe oder einer Datenbank? Und bist du sicher, dass er keine Zeichen mit Sonderbedeutung enthalten kann?
Eigentlich kommt der Wert aus meinem eigenem Formular - hab der einfachheit halber Radiobuttons verwendet - 500, 1000, 5000 usw. demzufolge kann eigentlich auch keine 'schädliche' Benutzereingabe erfolgen. Ich denke ich werde aber trotzdem deinen Quelltext mit einbinden kann nix schaden :)
Mfg
So wenn du mir jetzt noch erzählst wie ich in diesem SQL Query einen like-Ausdruck realisiere bin ich vollauf zufrieden.
echo $begrüßung;
So wenn du mir jetzt noch erzählst wie ich in diesem SQL Query einen like-Ausdruck realisiere bin ich vollauf zufrieden.
Wenn du das "irgendwas" selbst vorgibst:
$where[] = "feld LIKE '%irgendwas'";
Falls das "irgendwas" vom Benutzer kommt, muss da natürlich auch wieder ein Escaping stattfinden. Hier gibt es nun zwei Fälle.
1. Du gibst die Positionen der Jokerzeichen fest vor.
2. Der Benutzer soll die Jokerzeichen in seiner Eingabe setzen können. (Und hier wäre es sicher auch noch hübsch, wenn er * und ? verwenden könnte statt % und _ )
Fall 1: Es müssen die vom Benutzer eingegebenen %- und _-Zeichen entschärft werden. Das muss man selbst tun, da mysql_real_escape_string() sich darum nicht kümmert.
$irgendwas = strtr($irgendwas, array('%' => '\%', '_' => '\_', '\' => '\\')); // 2 bzw. 4 \ weil der PHP-Parser bei \ ein \ "wegparst".
Einsetzen in die LIKE-Konstruktion. Da das % auch von sprintf() verwendet wird muss es doppelt geschrieben werden, wenn du es an LIKE weiterreichen willst.
$where[] = sprintf("feld LIKE '%%%s'", mysql_real_escape_string($irgendwas)); // Joker steht vor dem $irgendwas; %% steht für ein LIKE-%, %s für einen String-Platzhalter.
$where[] = sprintf("feld LIKE '%s%%'", mysql_real_escape_string($irgendwas)); // Joker steht nach dem $irgendwas
Fall 2: Das Auflösen von * und ? nach % und _ kann man mit dem Escapen von % und _ verbinden.
$irgendwas = strtr($irgendwas, array('*' => '%', '?' => '_', '%' => '\%', '_' => '\_', '\' => '\\'));
$where[] = sprintf("feld LIKE '%s'", mysql_real_escape_string($irgendwas));
strtr() sorgt übrigens dafür, dass schon bearbeitete Bestandteile nicht ein zweites Mal umgewandelt werden, also ein * wird nur zum % und wird danach kein %:
echo "$verabschiedung $name";
So nun funktioniert alles - Vielen Dank für die Hilfe.
echo $begrüßung;
Eigentlich kommt der Wert aus meinem eigenem Formular - hab der einfachheit halber Radiobuttons verwendet - 500, 1000, 5000 usw. demzufolge kann eigentlich auch keine 'schädliche' Benutzereingabe erfolgen.
Der normale Nutzer macht sowas auch nicht, aber du kannst es nicht verhindern, dass jemand statt der vorgegebenen Werte etwas anderes sendet.
Ich denke ich werde aber trotzdem deinen Quelltext mit einbinden kann nix schaden :)
Im Gegenteil, es schützt dich vor dem Missbrauchsfall.
echo "$verabschiedung $name";
$ergebnis=mysql_query ("select * from hersteller where betriebssystem='$betriebssystem' and typ='$typ' and hersteller='$hersteller'");
ESCAPING VERGESSEN!!!!!!!!1!!elf! Verdammt.