Yadgar: Query funktioniert nicht

Hi(gh)!

Folgendes Problem: In eine MySQL-Tabelle sollen per HTML-Formular die Namen von Bundesländern eingetragen werden. Die Tabelle hat die Felder "id" (laufende Nummer, Primärschlüssel) und "name" (Name des Bundeslandes).

Hier der Codeteil, in dem der Fehler auftritt:

  $db = new mysqli("localhost", "root", "Passwort", "greenbook_lokal");
  if ($db->connect_error)
  {
    echo "Fehler bei der Verbindung:".mysqli_connect_error();
    exit();
  }
  else
  {
    $ergebnis = $db->query("INSERT INTO land (name) VALUES ".$bundesland.";");
  }
  var_dump($ergebnis);
  echo "$bundesland wurde eingegeben.\n";

Dass der Verbindungsaufbau funktioniert, erkenne ich daran, dass der erste Teil der if-Verzweigung offensichtlich nicht ausgeführt wird. Sehe ich aber anschließend mit phpmyadmin in der Tabelle nach, stelle ich fest, dass sie leer geblieben ist - und var_dump zeigt für $ergebnis false an. Warum?

Am nicht vorhandenen Inhalt von $bundesland kann es nicht liegen, das wird mir mit der letzten Codezeile einwandfrei angezeigt...

Bis bald im Khyberspace!

Yadgar

  1. Hallo Yadgar,

    Du solltest dir die Fehlermeldung von Mysql anzeigen lassen, vermute aber es liegt hier dran:

    '$bundesland' also: ' fehlt.

    Gruss
    Henry

    --
    Meine Meinung zu DSGVO & Co:
    „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
    1. Hallo Yadgar,

      Du solltest dir die Fehlermeldung von Mysql anzeigen lassen, vermute aber es liegt hier dran:

      '$bundesland' also: ' fehlt.

      So:

      $ergebnis = $db->query("INSERT INTO land (name) VALUES ".'$bundesland'.";");
      
      

      funktioniert es leider auch nicht! $bundesland bleibt false!

      1. Hallo

        $ergebnis = $db->query("INSERT INTO land (name) VALUES ".'$bundesland'.";");
        
        

        funktioniert es leider auch nicht! $bundesland bleibt false!

        Die Anführungszeichen müssen schon an den richtigen Stellen sitzen. Sie gehören zum Query.

        INSERT INTO land (name) VALUES 'Bayern';
        

        wird in PHP zu

        $query = "INSERT INTO land (name) VALUES '".$bundesland."';"
        

        Somit wäre zumindest die Syntax repariert. Dass damit kein Schutz vor SQL-Injection verbunden ist, ist die nächste Baustelle, die unbedingt anzugehen ist.

        Tschö, Auge

        --
        Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
        Hohle Köpfe von Terry Pratchett
        1. Hallo

          $query = "INSERT INTO land (name) VALUES '".$bundesland."';"
          

          Funktioniert immer noch nicht!

          Somit wäre zumindest die Syntax repariert. Dass damit kein Schutz vor SQL-Injection verbunden ist, ist die nächste Baustelle, die unbedingt anzugehen ist.

          Was ist "SQL-Injection"? Meinst du das Einschmuggeln von HTML oder JavaScript über Formulare? Dagegen habe ich das hier gemacht:

            $bundesland = lencheck($_POST["bundesland"], $lengths[0]);
            $bundesland = trim(htmlspecialchars($bundesland, ENT_QUOTES));
          
          

          lencheck ist eine selbst geschriebene Funktion, die die Eingabe nach Bedarf auf die maximal zulässige Länge kürzt.

          1. Hallo

            $query = "INSERT INTO land (name) VALUES '".$bundesland."';"
            

            Funktioniert immer noch nicht!

            Das habe ich auch nicht behauptet. 😉

            Henry hat aber schon den richtigen Weg gewiesen. Was steht denn in der MySQL-Fehlermeldung?

            Somit wäre zumindest die Syntax repariert. Dass damit kein Schutz vor SQL-Injection verbunden ist, ist die nächste Baustelle, die unbedingt anzugehen ist.

            Was ist "SQL-Injection"? Meinst du das Einschmuggeln von HTML oder JavaScript über Formulare?

            … oder SQL-Code, also Dinge, die in einer SQL-Abfrage Schaden anrichten. Dafür gibt es für Zeichenketten die Funktion mysqli_real_escape_string oder man präpariert seinen Query, wobei die Funktion je nach Datentyp „das Richtige“ macht.

            Dagegen habe ich das hier gemacht:

            … was gegen SQL-Injection nicht hilft.

              $bundesland = lencheck($_POST["bundesland"], $lengths[0]);
              $bundesland = trim(htmlspecialchars($bundesland, ENT_QUOTES));
            
            

            lencheck ist eine selbst geschriebene Funktion, die die Eingabe nach Bedarf auf die maximal zulässige Länge kürzt.

            Was ist laut deiner Definition zulässig? „Bayern“ oder „Berlin“ haben schließlich eine gänzlich andere Länge als „Baden-Württemberg“ oder gar „Nordrhein-Westfalen“.

            Tschö, Auge

            --
            Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
            Hohle Köpfe von Terry Pratchett
            1. Was in der MySQL-Fehlermeldung steht? Keine Ahnung - wie komme ich an die überhaupt ran?

              … oder SQL-Code, also Dinge, die in einer SQL-Abfrage Schaden anrichten. Dafür gibt es für Zeichenketten die Funktion mysqli_real_escape_string oder man präpariert seinen Query, wobei die Funktion je nach Datentyp „das Richtige“ macht.

              Das würde man dann also mit $query = mysqli_real-escape-string.php($query) absichern?

              Was ist laut deiner Definition zulässig? „Bayern“ oder „Berlin“ haben schließlich eine gänzlich andere Länge als „Baden-Württemberg“ oder gar „Nordrhein-Westfalen“.

              Ich habe einfach die Länge des längsten Ländernamens, also "Mecklenburg-Vorpommern" als zulässige Höchstlänge gewählt!

              1. Hallo

                Was in der MySQL-Fehlermeldung steht? Keine Ahnung - wie komme ich an die überhaupt ran?

                Echt jetzt? Benutze mysqli_errno für die Fehlernummer und mysqli_error für die Fehlermeldungstext. Irgendeiner deiner Schritte funktioniert nicht. Falls das bei der Kommunikation mit dem SQL-Server passiert, sollte es einen Fehler auslösen, der mit diesen Funktionen ermittelbar ist.

                … oder SQL-Code, also Dinge, die in einer SQL-Abfrage Schaden anrichten. Dafür gibt es für Zeichenketten die Funktion mysqli_real_escape_string oder man präpariert seinen Query, wobei die Funktion je nach Datentyp „das Richtige“ macht.

                Das würde man dann also mit $query = mysqli_real-escape-string.php($query) absichern?

                Nein. Es wird jeder String, der in den Query eingefügt wird, einzeln behandelt. Ganz so, wie es der verlinkte Eintrag in der PHP-Doku zeigt. Die Funktion heißt schließlich mysqli_real_escape_string und nicht mysqli_real_escape_query.

                Was ist laut deiner Definition zulässig? „Bayern“ oder „Berlin“ haben schließlich eine gänzlich andere Länge als „Baden-Württemberg“ oder gar „Nordrhein-Westfalen“.

                Ich habe einfach die Länge des längsten Ländernamens, also "Mecklenburg-Vorpommern" als zulässige Höchstlänge gewählt!

                Tschö, Auge

                --
                Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                Hohle Köpfe von Terry Pratchett
                1. Echt jetzt? Benutze mysqli_errno für die Fehlernummer und mysqli_error für die Fehlermeldungstext. Irgendeiner deiner Schritte funktioniert nicht. Falls das bei der Kommunikation mit dem SQL-Server passiert, sollte es einen Fehler auslösen, der mit diesen Funktionen ermittelbar ist.

                  … oder SQL-Code, also Dinge, die in einer SQL-Abfrage Schaden anrichten. Dafür gibt es für Zeichenketten die Funktion mysqli_real_escape_string oder man präpariert seinen Query, wobei die Funktion je nach Datentyp „das Richtige“ macht.

                  Das würde man dann also mit $query = mysqli_real-escape-string.php($query) absichern?

                  Nein. Es wird jeder String, der in den Query eingefügt wird, einzeln behandelt. Ganz so, wie es der verlinkte Eintrag in der PHP-Doku zeigt. Die Funktion heißt schließlich mysqli_real_escape_string und nicht mysqli_real_escape_query.

                  Ich verstehe nur Bahnhof! Mit jeder neuen Version werden sowohl PHP als auch MySQL komplizierter und schwerer zu verstehen... Anfang der 2010er Jahre hatte ich schon mal einen Anlauf zur Programmierung eines Datenbankprojekts genommen, da war ich noch erheblich weiter gekommen... ich glaube langsam wirklich, dass ich einfach zu dumm zum Programmieren bin - und Jahr für Jahr dümmer werde!

                  Ich bin bei wirklich allen Dingen, die ich vorhabe immer nur ganz am Anfang... außer Fahrradfahren und in Bibliotheken vom Afghanistan der Vorkriegszeit träumen kann ich eigentlich überhaupt nichts! Ach ja, Freeciv... da bin ich auch noch ganz gut drin!

                  1. Hallo

                    Ich verstehe nur Bahnhof! Mit jeder neuen Version werden sowohl PHP als auch MySQL komplizierter und schwerer zu verstehen... Anfang der 2010er Jahre …

                    … gab es exakt die selben Aufgaben, die zum Daten schreiben und lesen in einer MySQL-Datenbank zu erledigen waren [1]. Der einzige Unterschied ist die damals typischerweise verwendete Funktionsbibliothek (damals mysql_, heute mysqli_ oder PDO).

                    Das lesen der Dokumentation [2] und von Beispielen kann dir hier niemand abnehmen. Das wäre – abseits allen jammerns, weil es nicht beim ersten Versuch sofort und ohne Umschweife klappt – ein guter Anfang.

                    Tschö, Auge

                    --
                    Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                    Hohle Köpfe von Terry Pratchett

                    1. Verbindung herstellen, zu übertragende Daten kontextgerecht maskieren, Queries ausführen, Ergebnisse auslesen, auf Fehler reagieren, was auch immer ↩︎

                    2. Die Beschreibungen der entsprechenden Funktionen hatte ich verlinkt. ↩︎

                  2. Hallo Yadgar,

                    Ich verstehe nur Bahnhof! Mit jeder neuen Version werden sowohl PHP als auch MySQL komplizierter und schwerer zu verstehen... Anfang der 2010er Jahre hatte ich schon mal einen Anlauf zur Programmierung eines Datenbankprojekts genommen, da war ich noch erheblich weiter gekommen... ich glaube langsam wirklich, dass ich einfach zu dumm zum Programmieren bin - und Jahr für Jahr dümmer werde!

                    Ja es wird immer komplizierter wenn man immer uptodate sein will, tue mich auch selbst schwer damit. Aber zum Glück halten sich alle Neuerungen noch in Grenzen und/oder sind abwärtskompatibel.

                    In deinem Fall hier ist es aber was Grundsätzliches. PHP interpretiert keine Variabeln innerhalb ' und so war es auch nicht gemeint, die müssen in dem Query enthalten sein, weil sql die haben möchte. Also eher zb. so xyz.. '".$bundesland."'

                    Einfache nachvollziehbare Beispiele auch zur Fehlerprüfung findest du hier.

                    Gruss
                    Henry

                    --
                    Meine Meinung zu DSGVO & Co:
                    „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“
                    1. Hallo Yadgar,
                      Ja es wird immer komplizierter wenn man immer uptodate sein will, tue mich auch selbst schwer damit. Aber zum Glück halten sich alle Neuerungen noch in Grenzen und/oder sind abwärtskompatibel.

                      In deinem Fall hier ist es aber was Grundsätzliches. PHP interpretiert keine Variabeln innerhalb ' und so war es auch nicht gemeint, die müssen in dem Query enthalten sein, weil sql die haben möchte. Also eher zb. so xyz.. '".$bundesland."'

                      Einfache nachvollziehbare Beispiele auch zur Fehlerprüfung findest du hier.

                      Ich habe es so wie dort beschrieben versucht - und es klappt trotzdem nicht!

                      Hier die neueste Version meiner Eingaberoutine:

                        if ($db->connect_error)
                        {
                          echo "Fehler bei der Verbindung:".mysqli_connect_error();
                          exit(1);
                        }
                        else
                        {
                          $sql = "INSERT INTO land (name) VALUES '".$bundesland."';";
                          if ($db->query($sql) === TRUE)
                            echo "$bundesland wurde eingegeben.\n";
                          else
                            echo "Fehler: ".$sql."<br>".$db->error;
                        }
                      
                      

                      Als Fehlermeldung wurde ausgegeben:

                      Fehler: INSERT INTO land (name) VALUES 'Schleswig-Holstein'; You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Schleswig-Holstein'' at line 1

                      Immerhin wird mir das Gleiche auch angezeigt, wenn ich diesen Query auf der MySQL-Konsole eingeben... wenigstens ein bisschen Konsistenz in dieser chaotischen, unberechenbaren, unverstehbaren Computerwelt!

                      1. Hallo

                        Ich habe es so wie dort beschrieben versucht - und es klappt trotzdem nicht!

                        Hier die neueste Version meiner Eingaberoutine:

                        Du solltest dich auf eine Syntax festlegen. Hier vermischst du die objektorientierte mit der prozeduralen Schreibweise der MySQLi-Extension.

                          if ($db->connect_error)
                          {
                            echo "Fehler bei der Verbindung:".mysqli_connect_error();
                            exit(1);
                          }
                        

                        Wie im Beispiel in der Doku zu mysqli_connect_error für den objektorientierten Stil (den du ja überall sonst verwendest) gezeigt wird, lautet die korrekte Syntax für diesen Abschnitt:

                          if ($db->connect_error)
                          {
                            echo "Fehler bei der Verbindung:".$db->connect_error;
                            exit(1);
                          }
                        
                            $sql = "INSERT INTO land (name) VALUES '".$bundesland."';";
                        

                        Als Fehlermeldung wurde ausgegeben:

                        Fehler: INSERT INTO land (name) VALUES 'Schleswig-Holstein'; You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Schleswig-Holstein'' at line 1

                        Nun sieht man es klar, wie Kloßbrühe. Entweder du benutzt die spezielle MySQL-Schreibweise "INSERT INTO land SET name = '".$bundesland."';" oder die SQL-Standardschreibweise "INSERT INTO land (name) VALUES ('".$bundesland."');". Beachte das Klammerpaar, das VALUES folgt und alle Werte eines Datensatzes (bei dir ist es einer) einschließt.

                        Und wenn du nun noch die Maskierung durchführst, sollte der Code funktionieren. Das Beispiel für den objektorientierten Stil enthält die relevante Zeile

                        # Code aus dem Beispiel
                        $city = $mysqli->real_escape_string($city);
                        # an deinen Code angepasster Code des Beispiels
                        $bundesland = $mysqli->real_escape_string($bundesland);
                        

                        Bis auf die andere Syntax ist das das Gleiche, als hättest du die Bundesländer 2010 in einer MySQL-Datenbank speichern wollen.

                        Tschö, Auge

                        --
                        Ein echtes Alchimistenlabor musste voll mit Glasgefäßen sein, die so aussahen, als wären sie beim öffentlichen Schluckaufwettbewerb der Glasbläsergilde entstanden.
                        Hohle Köpfe von Terry Pratchett
                        1. Hi(gh)!

                          Hallo Du solltest dich auf eine Syntax festlegen. Hier vermischst du die objektorientierte mit der prozeduralen Schreibweise der MySQLi-Extension.

                            if ($db->connect_error)
                            {
                              echo "Fehler bei der Verbindung:".mysqli_connect_error();
                              exit(1);
                            }
                          

                          Wie im Beispiel in der Doku zu mysqli_connect_error für den objektorientierten Stil (den du ja überall sonst verwendest) gezeigt wird, lautet die korrekte Syntax für diesen Abschnitt:

                            if ($db->connect_error)
                            {
                              echo "Fehler bei der Verbindung:".$db->connect_error;
                              exit(1);
                            }
                          

                          O.k., ich habe es angepasst!

                              $sql = "INSERT INTO land (name) VALUES '".$bundesland."';";
                          

                          Als Fehlermeldung wurde ausgegeben:

                          Fehler: INSERT INTO land (name) VALUES 'Schleswig-Holstein'; You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Schleswig-Holstein'' at line 1

                          Nun sieht man es klar, wie Kloßbrühe. Entweder du benutzt die spezielle MySQL-Schreibweise "INSERT INTO land SET name = '".$bundesland."';" oder die SQL-Standardschreibweise "INSERT INTO land (name) VALUES ('".$bundesland."');". Beachte das Klammerpaar, das VALUES folgt und alle Werte eines Datensatzes (bei dir ist es einer) einschließt.

                          Na endlich... jetzt leuchtet es mir auch ein! Ich habe jetzt die beiden Klammern gesetzt, und es funktioniert! Danke für den Hinweis!

                          Bis auf die andere Syntax ist das das Gleiche, als hättest du die Bundesländer 2010 in einer MySQL-Datenbank speichern wollen.

                          Nun ja, ich erinnere mich, dass ich damals an solchen syntaktischen Feinheiten auch fast irre geworden wäre... aber entweder hatte ich damals noch stärkere Nerven, so daß ich trotzdem weitergemacht hatte... oder weniger Alltagsschlamassel um die Ohren! Spülenputzenaufräumenspülenputzenaufräumen, das kostet mich Jahr für Jahr mehr Überwindung... kein Wunder, wenn ich immer fetter werde (BMI z. Z. 42) und mittlerweile schon nach 10 Minuten, die ich nicht bequem vorm Computer sitze, Rückenschmerzen habe!

                          Es muss doch möglich sein, ohne diese prollige Hausfrauenscheiße zu leben...

                          Bis bald im Khyberspace!

                          Yadgar

                      2. Hallo Yadgar,

                        Du übersiehst was.

                        $sql = "INSERT INTO MyGuests (firstname, lastname, email) VALUES ('John', 'Doe', 'john@example.com')";

                        ist nicht wie:

                        $sql = "INSERT INTO land (name) VALUES '".$bundesland."';";

                        "VALUES ('.... "

                        Gruss
                        Henry

                        --
                        Meine Meinung zu DSGVO & Co:
                        „Principiis obsta. Sero medicina parata, cum mala per longas convaluere moras.“