Forum: PC-Programmierung PHP: Error in your SQL syntax


von Flo (Gast)


Lesenswert?

Hallo,

ich versuche seit einigen Stunden vergeblich einen leeren Return von 
einer SQL Abfrage abzufangen.

Vereinfacht mache ich folgendes:
1
<?php
2
$user_agent = $_SERVER['HTTP_USER_AGENT'];
3
$connection = mysql_connect($server,$user,$password);
4
$db = mysql_select_db($database,$connection);
5
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";
6
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
7
  
8
if(mysql_num_rows($browser_result)<1){
9
10
$insert_sql = "INSERT INTO BrowserOS (browser) VALUES ($user_agent);";
11
$insert_result = mysql_query($insert_sql) OR die(mysql_error());
12
};

Also den Browser des Aufrufenden ermitteln, wenn dieser noch nicht in 
der Tabelle BrowserOS steht, dann eintragen.

Jedoch bekomme ich jedes mal wenn der Browser noch nicht in der Tabelle 
steht, folgende Fehlermeldung bei der Abfrage 
"if(mysql_num_rows($browser_result)<1){" --> You have an error in your 
SQL syntax; check the manual that corresponds to your MySQL server 
version for the right syntax to use near '(Windows NT 6.1; 
WOW64).....1985.' at line 1

Sobald ich die Abfrage auskommentiere und damit diesen Wert in die 
Datenbank schreiben lasse, kommt keine Fehlermeldung.

Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert.


Habt hier noch jemand einen Tip für mich?

von K. J. (Gast)


Lesenswert?

so richtig kenne ich mich damit nicht aus aber ich würde auf das ";" in 
der abfrage tippen.

von Peter II (Gast)


Lesenswert?

Flo schrieb:
> Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert.

dann liefere doch einfach einen wert zurück:

$browser_sql  = "SELECT Count(*) as Anz FROM `BrowserOS` WHERE browser = 
'$user_agent'";

und dann solltest du dich mir Prepared SQL beschäftigen, denn so hast du 
schon die erste Sicherheitslücke in deinem Programm.

von eingast (Gast)


Lesenswert?

Flo schrieb:
> $insert_sql = "INSERT INTO BrowserOS (browser) VALUES ($user_agent);";

versuche es mal damit:

$insert_sql = "INSERT INTO BrowserOS (browser) VALUES ('$user_agent');";

von Flo (Gast)


Lesenswert?

eingast schrieb:
> versuche es mal damit:
>
> $insert_sql = "INSERT INTO BrowserOS (browser) VALUES ('$user_agent');";

Der Insert ist nicht das Problem, wenn ich die if Abfrage auskommentiere 
dann trägt er den Wert richtig ein, das Problem liegt nur in der Abfrage 
wenn es noch keinen Eintrag gibt..

Das mit Count ist eine gute Idee, das werde ich ausprobieren

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";

Warum hier "Backticks" um BrowserOS und Hochkommata um $user_agent,
1
$insert_sql = "INSERT INTO BrowserOS (browser) VALUES ($user_agent);";

... wenn sie hier nicht nötig sind?

von Karl H. (kbuchegg)


Lesenswert?

Vor allen Dingen fehlt hier ein ; im SQL Statement
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";

--->
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent';";


Wie MySQL das handhabt kann ich nicht sagen, aber in den Command Line 
Tools wirkt sich so ein fehlender ; so aus, dass damit das SQL Statement 
noch nicht vollständig ist und mit der nächsten Eingabe weiter geht. 
Wenn das dazu führt, dass damit in einem einzigen SQL Statement sowohl 
ein SELECT als auch ein INSERT vorkommt, dann setzt das einen Fehler.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Warum hier "Backticks" um BrowserOS und Hochkommata um $user_agent,
> $insert_sql = "INSERT INTO BrowserOS (browser) VALUES ($user_agent);";
>
> ... wenn sie hier nicht nötig sind?

ja sieht merkwürdig aus, ist aber ok.

von Flo (Gast)


Lesenswert?

das war dann ein Copy&Paste Fehler von mir... habe mir teilweise die 
Querys aus PHPMyadmin kopiert.

ich habe es jetzt mal mit count versucht, an das Ergebnis (im moment 0 
weil die Tabelle leer ist) komme ich noch nicht ganz:
1
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
2
$count = mysql_result($browser_result);
3
  
4
if($count == 0){
5
  $insert_sql = "INSERT INTO BrowserOS (browser) VALUES $user_agent);";
6
  $insert_result = mysql_query($insert_sql) OR die(mysql_error());
7
  echo "Wird hinzugefuegt";    
8
    };


Ich glaube mysql_result($browser_result); ist hier nicht das richtige 
oder?
Es kommt weiterhin:You have an error in your SQL syntax; check the 
manual that corresponds to your MySQL server version for the right 
syntax to use near '(Windows NT 6.1; WOW64)...'

von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> Vor allen Dingen fehlt hier ein ; im SQL Statement

nein, auch das ist nicht der Fehler. Das Braucht man um im Client das 
Kommando an den Server zu übergeben. Wenn man die Datenbank über PHP 
anspricht ist es nicht notwendig.

von Flo (Gast)


Lesenswert?

vergessen:  $browser_sql  = "SELECT count(*) FROM `BrowserOS` WHERE 
browser = '$user_agent'";

von eingast (Gast)


Lesenswert?

Flo schrieb:
> Der Insert ist nicht das Problem, wenn ich die if Abfrage auskommentiere
> dann trägt er den Wert richtig ein, das Problem liegt nur in der Abfrage
> wenn es noch keinen Eintrag gibt..

Würde ich jetzt mal so nicht behaupten, denn die Fehlermeldung deutet 
auf das ";" in der Browserbezeichnng hin, welches als SQL-Kommandoende 
interpretiert wird. Deshalb versuche es erstmal mit den "'" und dann 
kann man weiter diskutieren!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Flo schrieb:
> Ich glaube

Lieber Doku lesen als glauben... Dein Problem ist NICHT irgendwelche 
Funktionsaufrufe oder existierende Tabelle(spalten) sondern das dein 
Query falsch ist. String müssen IMMER mit 
http://php.net/manual/de/function.mysql-real-escape-string.php escaped 
(und in Hochkomma eingeschlossen o.ä.) werden weil sonst teile des 
String (wie er dir ja auch sagt) als SQL Befehl interpretiert werden.

> Also kommt der Fehler nur wenn der Mysql keine Tabellen zurückliefert
Wenn der keine Tabbellen mehr hat ist was anderes kaputt...

> bei der Abfrage "if(mysql_num_rows($browser_result)<1){"
Höchst unwahrscheinlich, da hier ÜBERHAUPT kein SQL ausgeführt wird!

: Bearbeitet durch User
von Flo (Gast)


Lesenswert?

eingast schrieb:
> Würde ich jetzt mal so nicht behaupten, denn die Fehlermeldung deutet
> auf das ";" in der Browserbezeichnng hin, welches als SQL-Kommandoende
> interpretiert wird. Deshalb versuche es erstmal mit den "'" und dann
> kann man weiter diskutieren!

SUPER, danke, der Fehler kam vom insert...

Jetzt habe ich es so:
1
    
2
$browser_sql  = "SELECT count(*) FROM `BrowserOS` WHERE browser = $user_agent'";
3
   
4
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
5
$count = mysql_result($browser_result);
6
  
7
if($count == 0){
8
  $insert_sql = "INSERT INTO BrowserOS (browser) VALUES    ('$user_agent')";
9
  $insert_result = mysql_query($insert_sql) OR die(mysql_error());
10
  echo "Wird hinzugefuegt";    
11
    };

leider Ignoriert er jetzt das if($count == 0) und macht den Insert bei 
jedem aufruf.

von eingast (Gast)


Lesenswert?

Flo schrieb:
> leider Ignoriert er jetzt das if($count == 0) und macht den Insert bei
> jedem aufruf.

das ist ein anderes Thema und dabei wird dir die Doku helfen...

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Flo schrieb:
> SUPER, danke, der Fehler kam vom insert...

Ach...

Flo schrieb:
> leider Ignoriert er

Würd' ich auch machen wenn jemand zu faul ist mal strukturiert 
vorzugehen...

von Peter II (Gast)


Lesenswert?

Flo schrieb:
> $count = mysql_result($browser_result);
>
> if($count == 0){

ist ja auch Blödsinn.

woher soll er denn wissen welche Spalte du haben willst?

von Peter II (Gast)


Lesenswert?

Nachtrag:

du musst doch mindestens erst mal eine Zeilen "fetchen" und dann kann 
man von der Zeile eine Spalte abfragen.

von Karl H. (kbuchegg)


Lesenswert?

Schon wieder ein COpy&Paste Fehler, oder fehlt hier tatsächlich ein ' 
vor dem $user_agent?
1
$browser_sql  = "SELECT count(*) FROM `BrowserOS` WHERE browser = $user_agent'";

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Flo schrieb:
>> $count = mysql_result($browser_result);
>>
>> if($count == 0){
>
> ist ja auch Blödsinn.
>
> woher soll er denn wissen welche Spalte du haben willst?

Ich denke, die Idee ist sich zu fragen, wieviele Records überhaupt im 
Ergebnis vorliegen.

von Εrnst B. (ernst)


Angehängte Dateien:

Lesenswert?

Und: mach das unbedingt noch sicher!

Wie oben schon geschrieben: So ist das eine Sicherheitslücke.

Der "User Agent" ist vom Webseiten-Besucher frei vorgebbar,

Der Erste Besucher mit User-Agent
1
'; drop database; --

Bereitet dir viel Freude.

Und ja: Es gibt Tools um solche Lücken automatisch zu finden und 
auszunutzen.

: Bearbeitet durch User
von Flo (Gast)


Lesenswert?

Das Problem lag nur am Insert, ich habe es jetzt wie folgt gelöst:
1
$browser_sql  = "SELECT * FROM `BrowserOS` WHERE browser = '$user_agent'";
2
$browser_result = mysql_query($browser_sql) OR die(mysql_error());
3
    
4
    if(mysql_num_rows($browser_result)<1){  
5
    $insert_sql = "INSERT INTO BrowserOS (browser) VALUES  
6
                ('$user_agent')";
7
    $insert_result = mysql_query($insert_sql) OR 
8
                die(mysql_error());
9
    echo "Wird hinzugefuegt";    
10
    };

Εrnst B✶ schrieb:
> Und: mach das unbedingt noch sicher!
>
> Wie oben schon geschrieben: So ist das eine Sicherheitslücke.
>
> Der "User Agent" ist vom Webseiten-Besucher frei vorgebbar,

Wäre das eine mögliche Lösung?
$user_agent = str_replace("'","Einbruchsversuch",$user_agent);

von TestX .. (xaos)


Lesenswert?

Flo schrieb:
> Wäre das eine mögliche Lösung?
> $user_agent = str_replace("'","Einbruchsversuch",$user_agent);

Nein! Schmeiß deinen SQL Kram komplett weg! Die mysql_ / mysqli_ 
funktionen stammen aus den Anfängen von PHP und werden leider durch 
unzählige Tutorials so weitergegeben...heute benutzt man die Funktionen 
nur noch für eigene DB-Abstraktionsschichten...

Du solltest konkret PDO mit "Prepared Statements" benutzen - siehe 
http://php.net/manual/de/book.pdo.php - das verhindert jegliche Probleme 
dieser Art! Jede Variable wird über "bind(key, value)" dem Statement 
hinzugefügt und automatisch escaped

Dazu gibts auch unmengen an Tutorials im Internet...wenn du dir selber 
einen gefallen tun willst befolge den Rat...

von Εrnst B. (ernst)


Lesenswert?

Flo schrieb:
> Wäre das eine mögliche Lösung?
> $user_agent = str_replace("'","Einbruchsversuch",$user_agent);

Nicht wirklich.
etwas besser wäre "addslashes", "mysql_escape_string", oder besser 
"mysql_real_escape_string".

Eine Richtige Lösung sind alle drei auch nicht.
Besser: Ein neueres mysql-Interface nehmen, nicht das steinalte 
"mysql_*"-Zeuchs. Gerade bei Neuentwicklungen gibt es da eigentlich 
garkeinen Grund mehr für.

http://php.net/manual/de/mysqli.quickstart.prepared-statements.php
Oder besser gleich PDO-Mysql.

von Flo (Gast)


Lesenswert?

Super, danke für den Tip! Ich habe mir mal eben ein Beispiel gesucht und 
es auf meine Anwendung angepasst, das mit dem schließen ist mir noch 
etwas unklar...
1
<?php 
2
$handler = new mysqli("dbhost", "dbuser", "dbpass", "db");
3
4
$getuseragent = $handler->prepare("SELECT * FROM people WHERE (user_agent = ?)");
5
$getuseragent->bind_param('s', $user_agent);
6
$user_agent = $_SERVER['HTTP_USER_AGENT'];
7
$getuseragent->execute();
8
  
9
if (!$getuseragent->get_result()) {
10
    echo("Browser nicht vorhanden, wird hinzugefuegt...");
11
    $insertbrowser = $handler->prepare("INSERT INTO BrowserOS (browser) VALUES (?)");
12
  $insertbrowser->bind_param("s", $browsername);
13
  $name = $user_agent;
14
    $insertbrowser->execute();
15
  //nicht sicher ob das hier stimmt
16
  $insertbrowser->close();
17
    
18
}; 
19
  //nicht sicher ob das hier stimmt
20
$getuseragent->close();
21
 ?>

von Peter II (Gast)


Lesenswert?

Flo schrieb:
> if (!$getuseragent->get_result()) {
>     echo("Browser nicht vorhanden, wird hinzugefuegt...");

das sieht mir komisch aus. Auch ein leeres Result ist auch ein Result. 
Es kommt aus einen Select immer eine Result zurück, eventuell hat es 
aber 0 Zeilen.

von Flo (Gast)


Lesenswert?

vermutlich ist es dann so besser:
$getuseragent->execute();
$getuseragent->store_result();

if ($stmt->num_rows<1) {
....

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Wenn man die Anzahl haben will sollte man sie auch einfach abrufen...
1
SELECT count(*) as count FROM people WHERE (user_agent = ?)
Spart dem DB server allen möglichen Quatsch zu übertragen den du eh nie 
auswertest...

: Bearbeitet durch User
von Slin (Gast)


Lesenswert?

Falls du noch keine Lösung hast:

http://php.net/manual/de/function.mysql-num-rows.php


<?php

$link = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("database", $link);

$result = mysql_query("SELECT * FROM table1", $link);
$num_rows = mysql_num_rows($result);

echo "$num_rows Zeilen\n";

?>

Auf ersten Augenblick schein mir so zu sein (ich hab nicht ausprobiert):
Du hast den Connection ($link) für mysql_query nicht übergeben. Damit 
ist es ein Aufrufproblem (kein SQL Problem an der Stelle), $result war 
undefiniert, und dann bei mysql_num_rows ist es rausgestiegen.

Das ist nur ein Tipp ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.