Andreas Nagel: Tabellennamen in der SQL funktioniert nicht mit Leerzeichen

Hallo zusammen,

ich verwende auf meiner Seite verschiedene Datenbanken und Tabellen um meine Linksammlung zu speichern.Man kann den Namen der Datenbereiche, in diesen ein Link gespeichert werden soll frei wählen, so dass es zu richtig Text kommen kann.

Doch hab ich damit das Problem, dass mir die sql Anweisungen stets ein Fehler bringen, dass in der sql ein Fehler sein soll:

INSERT INTO $Database.$Table (Name,Bild,Hoch,Breit,Url,Infos,Daten,Datei) VALUES('$Bezeichner','$Bild','$Hoch','$Breit','$Adresse','$Infos','$Daten','$Datei')

Doch erhalte ich dann zB die Message zurück:

Error:
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 'Links (Name,Bild,Hoch,Breit,Url,Infos,Daten,Datei) VALUES('test','','','','http:' at line 1

Und dann schreib ich es in Anführungszeichen und erhalte dann wenigstens den kompletten Text der Datenbank und der Tabelle in der Fehlermeldung zurück. Ich meldete mich ja schonmal bei Euch wegen eines anderen Problems das auch in Verbindung mmit diesen Zeichen gelöst werden konnte. Ich hatte mich für diese, zur Realisierung meiner Wünsche führende Hilfestellung nicht bedankt, wofür ich mich auch jetzt entschuldig,. sowie auch sehr dafür bedanke. Doch jetzt kopiere ich diese Schreibweise in die sql und erhalte so oder so eine Fehlermeldung zurück. Also sprich in Anführungszeichen oder ohne oder mit oder ohne ÄDatenbank.

Sobald ein Leerzeichen vorhanden ist, gehts irgendwie nicht. Also was nun? Und ich würde mich sehr über Eure Hilfe freuen, da hinzufügen und löschen mit allen Namensgebungen die Nutzung erst richtig möglich machen würde.

Also auf jeden Fall schonmal Vielen Dank für jede Mühe

Und damit Danke Gruß Andreas

  1. Tach!

    Sobald ein Leerzeichen [im Tabellennamen] vorhanden ist, gehts irgendwie nicht. Also was nun?

    Bitte lies das Kapitel zu Schema Object Names. Quoten allen reicht nicht, du must auch bestimmte Sachen verbieten, weil MySQL dies ebenfalls nicht erlaubt (beispielsweise Space am Ende).

    Im ersten Unterkapitel (Identifier Qualifiers) steht auch noch Information zur Kombination von Datenbank- und Tabellennamen.

    dedlfix.

    1. Jo Hallo

      und Vielen Dank. Doch ist es ja so gewesen, dass ich mich damals bezüglich einer UPDATE Anweisung gemmeldet hatte, die jetzt in allen Tabellen funktioniert:

      UPDATE '$Table' SET Sub = $View WHERE ID = $ID

      Doch wieso ich hier nicht zum Ziel komme, sollte vielleicht an der Kombination mit der gesamten Schreibweise liegen. Also ich würde mich schon sehr freuen wenn ich erfahren könnte wie ich das schreiben solle.

      Auf jeden Fall Vielen Dank Gruß Andreas

      1. Tach!

        UPDATE '$Table' SET Sub = $View WHERE ID = $ID

        Backticks ` und keine einfachen Anführungszeichen ' wären die richtigen Maskierzeichen.

        Doch wieso ich hier nicht zum Ziel komme, sollte vielleicht an der Kombination mit der gesamten Schreibweise liegen.

        Kann gut sein, aber hellsehen kann ich nicht. Du musst schon zeigen, wie das fertige Statement aussieht, damit man dir den Fehler aufzeigen kann.

        dedlfix.

  2. Lieber Andreas,

    INSERT INTO $Database.$Table (Name,Bild,Hoch,Breit,Url,Infos,Daten,Datei) VALUES('$Bezeichner','$Bild','$Hoch','$Breit','$Adresse','$Infos','$Daten','$Datei')
    

    wie @dedlfix schon richtig schrieb, brauchst Du für die Bezeichner Backticks:

    $sql = sprintf(
        'INSERT INTO `$1$s`.`%2$s` ('
        .' `Name`,'
        .' `Bild`,'
        .' `Hoch`,'
        .' `Breit`,'
        .' `Url`,'
        .' `Infos`,'
        .' `Daten`,'
        .' `Datei`'
        .') VALUES ('
        ."'%3\$s',"
        ."'%4\$s',"
        ."'%5\$s',"
        ."'%6\$s',"
        ."'%7\$s',"
        ."'%8\$s',"
        ."'%9\$s',"
        ."'%10\$s'"
        .')',
        // Werte alle erst noch SQL-gerecht escapen! SONST SLQ-INJECTION LÜCKE!!!
        $Datenbank,
        $Table,
        $Bezeichner,
        $Bild,
        $Hoch,
        $Breit,
        $Adresse,
        $Infos,
        $Daten,
        $Datei
    );
    

    Ich arbeite mit der PDO-Erweiterung in PHP. Dort macht man das im Prinzip so:

    $dsn = "mysql:host=localhost;dbname=$Datenbank";
    $user = 'username';
    $pass = 'password';
    $options = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
    );
    $dbh = new PDO($dsn, $user, $pass, $options);
    
    $sql = sprintf(
        'INSERT INTO `:table` ('
        .' `Name`, `Bild`, `Hoch`, `Breit`, `Url`, `Infos`, `Daten`, `Datei`'
        .') VALUES ('
        .':bezeichner, :bild, :hoch, :breit, :adresse, :infos, :daten, :datei'
        .')';
    
    $params = array(    
        ':bezeichner' => $Bezeichner,
        ':bild' => $Bild,
        ':hoch' => $Hoch,
        ':breit' => $Breit,
        ':adresse' => $Adresse,
        ':infos' => $Infos,
        ':daten' => $Daten,
        ':datei' => $Datei
    );
    
    $statement = $dbh->prepare($sql);
    $statement->execute($params);
    

    Das Beispiel hat aber noch keine Fehlerbehandlung. Dafür werden aber die Variablenwerte korrekt SQL-gemäß escaped.

    Liebe Grüße,

    Felix Riesterer.

    1. Tach!

      $sql = sprintf(
          'INSERT INTO `$1$s`.`%2$s` ('
          .' `Name`,'
          // ...
          .') VALUES ('
          ."'%3\$s',"
          // ...
          .')',
          // Werte alle erst noch SQL-gerecht escapen! SONST SLQ-INJECTION LÜCKE!!!
          $Datenbank,
          $Table,
          $Bezeichner,
          $Bild,
          // ...
      );
      

      Ja, "Werte alle erst noch SQL-gerecht escapen!". Aber Datenbank- und Tabellenname sind keine Werte. Die benötigen ein anderes Escaping, weil da ja der Backtick berücksichtigt werden muss und nicht die einfachen oder doppelten Anführungszeichen.

      Ich arbeite mit der PDO-Erweiterung in PHP. Dort macht man das im Prinzip so:

      $sql = sprintf(
          'INSERT INTO `:table` ('
          .' `Name`, `Bild`, `Hoch`, `Breit`, `Url`, `Infos`, `Daten`, `Datei`'
          .') VALUES ('
          .':bezeichner, :bild, :hoch, :breit, :adresse, :infos, :daten, :datei'
          .')';
      
      $params = array(    
          ':bezeichner' => $Bezeichner,
          ':bild' => $Bild,
          ':hoch' => $Hoch,
          ':breit' => $Breit,
          ':adresse' => $Adresse,
          ':infos' => $Infos,
          ':daten' => $Daten,
          ':datei' => $Datei
      );
      

      Auf den ersten Blick fehlt in $params der Wert für table. Aber wenn man genau nachdenkt und obigen Punkt berücksichtigt, muss man zum Schluss kommen, dass das :table im Statement falsch ist. Einem Prepared Statement kann man nur Werte aber keine Bezeichner via Platzhalter übergeben.

      Stell dir mal vor, eine Datenbankabstraktion würde Prepared Statements nur simulieren und dabei das SQL-Statement selbst zusammenbauen. Es müsste dann das Statement parsen und analysieren, um feststellen zu können, dass der eine Parameter da ein Tabellenname ist und anders behandelt werden muss. Das wäre eine Menge Arbeit und es wäre dann auch noch inkompatibel zu echten Prepared Statements.

      dedlfix.

  3. In diesem Fall würde ich dir raten dir ein anderes Konzept zu suchen. Tabellennamen oder Spaltennamen mit Leerzeichen oder sonstigen Sonderzeichen machen dir wirklich überall nur Probleme. Irgendwann kommst du vielleicht doch mal an ein System das damit nicht klar kommt, vielleicht willst du mal was exportieren oder in anderen Programmen verarbeiten lassen.
    Was passiert wenn in deinem Text ein Anführungszeichen vorkommt?
    Da sehe ich Ärger und Stress vorprogrammiert. Überlege dir gut ob es dir wert ist.

    Wenn du sagst was du damit vorhast findet sich vielleicht eine andere Lösung.

    1. Jo Hallo zusammen,

      OK also dann mal vielenn Dank an Euch zusammen. Die sql Anweisung passt dank dedlfix einwandfrei. Ich hatte halt den Text aus einer anderen sql rauskopiert und sagte ja bereits, dass ich mich schon einmal bezüglich solch eines Problems hier meldete und auch hier eine Hilfeleistung erhalten hatte, die sich auf die Striche bezog. Auch sie führte zum Erfolg, nur frage ich mich in ganzer Anfängermanier, wie ich denn solche Striche hinbekommen/eingeben kann?

      Aber es funktioniert ja jetzt allein mit dem bei der Angabe des Tabellennamens. Alles weitere wird wohl akzeptiert und die Datenbank bezieht sich ja nur auf meine Webseite. Doch kann ich mich ja nur auch für all die weiteren Infos bei Euch bedanken.

      Ich hätte wie gesagt noch gerne die Info zu dem zeichen, aber auf jeden Fall vielen Dank.

      Gruß Andreas

      1. Tach!

        nur frage ich mich in ganzer Anfängermanier, wie ich denn solche Striche hinbekommen/eingeben kann?

        Kommt auf deine Tastatur und deinen Tastaturtreiber an. Ausgehend von deutscher Tastatur und entsprechendem Treiber nimmst du die Taste rechts oberhalb vom Ü oder rechts vom ß?\ und dazu noch Shift (Umschalt). Dann passiert erstmal nichts sichtbares, weil die beiden Zeichen auf dieser Taste meist mit Vokalen zusammen Akzent-Zeichen ergeben: è é ... Aber mit der Leertaste danach gedrückt gibt es das Zeichen auch einzeln. Und zur Not kopiert man es sich einfach irgendwoher.

        dedlfix.

        1. Hallo dedlfix,

          Aber mit der Leertaste danach gedrückt gibt es das Zeichen auch einzeln.

          Oder einfach doppelt drücken, dann hat man zwei ``. Nach einem Tastendruck auf ← kann man zwischen den Backticks weiterschreiben. Und man vergisst nicht versehentlich das schließende Zeichen. Außerdem ists ein Tastendruck weniger. ;-)

          Bis demnächst
          Matthias

          --
          Wenn eine Idee nicht zuerst absurd erscheint, taugt sie nichts. (Albert Einstein)
          1. Hallo

            Aber mit der Leertaste danach gedrückt gibt es das Zeichen auch einzeln.

            Oder einfach doppelt drücken, dann hat man zwei ``.

            Das ist betriebssystemabhängig. Unter Windows 7 kenne ich das von dir beschriebene Verhalten. Unter Ubunut 15.10 erhalte ich nach zwei Drücken der Tastenkombi einen Backtick. …

            Nach einem Tastendruck auf ← kann man zwischen den Backticks weiterschreiben. Und man vergisst nicht versehentlich das schließende Zeichen.

            … Ich kann dann natürlich weiterschreiben, darf aber das schließende Backtick nicht vergessen.

            Außerdem ists ein Tastendruck weniger. ;-)

            Dieser Faulheitsbonus bleibt mir unter Linux verwehrt. :-)

            Tschö, Auge

            --
            Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
            Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
            1. Das ist betriebssystemabhängig.

              Genauer gesagt: Einstellungsabhängig.