• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

MySQL mit PHP Zeichensatzproblem

PHP Anfänger

Neues Mitglied
Hallo zusammen,

ich versuche über PHP einige DAten mit Sonder- und Leerzeichen, sowie Umlauten, in eine MySQL-Datenbank einzugeben.
Doch dabei treten Fehler auf "Check your Syntax near '[Sonderzeichen]'...".
Sonderzeichen und Umlaute kann ich aber doch in der Datenbank speichern.
Das Problem liegt also wohl in der Konvertierung des Browser-Zeichensatzes in das UTF-8-Format von MySQL.
Ich habe mal utf8_encode() versuch, klappt aber auch nicht.
Auch den Zeichensatz der Tabelle habe ich geändert, ebenfalls ohne Erfolg.
Wo liegt das Problem, was mache ich falsch?
Über Eure Hilfe würde ich mich sehr freuen.

Viel Grüße!
 
Hallo,

hier der Code, er liest Tab-Seperatierte Text-Dateien ein:
PHP:
$db = mysql_connect();
$res = mysql_db_query("$Datenbank", "delete from $Tabelle");
$columns = mysql_db_query("$Datenbank", "show columns from $Tabelle");
$n = mysql_num_rows($columns);
for($i=2; $i<=$n; $i++ ){
$name = mysql_result($columns, $i - 1, "Field");
$a = mysql_db_query("$Datenbank", "alter table $Tabelle drop $name");
}
$filename = $_GET["dateiname"];
$file = file($filename);
$Kopf = explode("\t", $file[0]);
$name = mysql_result($columns, 0, "Field");
$b = $Kopf[0];
$a = mysql_db_query("$Datenbank", "alter table $Tabelle change $name $b text(255)");
print mysql_error();
for($i=2; $i<=count($Kopf); $i++) {
$b = $Kopf[$i - 1];
$a = mysql_db_query("$Datenbank", "alter table $Tabelle add $b text(255)");
print mysql_error();
}
for ($i=2; $i<=count($file); $i++) {
$Insert = $file[$i-1];
$Insert = str_replace("\t", "','", $Insert);
$Insert = "'".$Insert."'";
$a = mysql_db_query("$Datenbank", "insert $Tabelle values($Insert)");
print mysql_error();
}
mysql_close($db);
 
Hier noch mal der genaue Fehler:
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 '[Name mit Sonderzeichen] text(255)' at line 1
 
Sendest du im String z.B ein ' oder " dann muss das escaped werden, da sonst dein SQL-Statement zerhackt wird.
Also htmlspecialchars und mysql_real_escape_string verwenden.
 
Das Problem liegt also wohl in der Konvertierung des Browser-Zeichensatzes in das UTF-8-Format von MySQL.

Was Du nicht machen müsstest, wenn Du sowohl in der Webseite als auch in MySQL UTF-8 als Zeichensatz verwenden würdest. Dabei musst Du aber auch darauf achten eine UTF-8-Verbindung zu MySQL aufzubauen. Das machst Du soweit ich sehen kann jedoch nicht. Schau dich mal hier im Forum wie auch bei Tante Google nach "SET CHARSET" in Verbindung mit MySQL um.

Auch den Zeichensatz der Tabelle habe ich geändert, ebenfalls ohne Erfolg.
Bitte sowas nie machen, wenn schon Daten enthalten sind. Dadurch machst Du dir nur die Daten kaputt.

Code:
$res = mysql_db_query("$Datenbank", "delete from $Tabelle");

Hier wie auch bei allen anderen Statements in deinem Script-Ausschnitt sehe ich 4 Probleme:

- Du schließt php-Variablen nicht korrekt in den String ein, das sähe nämlich so aus:

Code:
mysql_db_query([COLOR=red]$Datenbank[/COLOR], "delete from [COLOR=red]".$Tabelle[/COLOR]);
- Du verwendest kein mysql_escape_string um Variablen beim Einbinden in SQL-Statements zu escapen:

Code:
mysql_db_query($Datenbank, "delete from [COLOR=red]".mysql_escape_string($Tabelle)[/COLOR]);
- Du verwendest kein mysql_error()
- Du verwendest kein SET CHARSET um den Zeichensatz der MySQL-Verbindung zu setzen.

Hier noch mal der genaue Fehler:
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 '[Name mit Sonderzeichen] text(255)' at line 1

Was ist Zeile 1 in deinem Script?
 
Also, die Fehlermeldung kommt meines Erachtens definitiv von MySQL und hat nur insofern etwas mit dem PHP-Skript zu tun, als dass dieses sie falsch generiert. Zeile 1 bezieht sich auf die Query, die vermutlich ohnehin nur aus einer Zeile besteht.

Das kann natürlich ein Encoding-Problem sein. Offenbar geht es an der Stelle um einen Spaltennamen, das text(255) – ist da nicht varchar gemeint? – und die Zeilen im Skript sind Data Definition Language. Ich habe eben etwas erfolglos versucht, herauszufinden, welche Zeichen in Spaltennamen erlaubt sind. Generell würde ich nicht empfehlen, Zeichen zu verwenden, die nicht in ASCII-7 liegen, aber offenbar sieht MySQL das nicht so strikt. Das könnte wie gesagt für ein Encoding-Problem sprechen, muss aber nicht. Es fehlen die Informationen, um das genauer beurteilen zu können. In den in die Query eingesetzten Variablen kann alles stehen und Escaping findet eben nicht statt.
 
In Zeichenketten sind alle bekannten Formen von Zeichenketten erlaubt. Wenn ich mich recht erinnere, zählt varchar die Zeichen und achtet nicht auf den Platz, den die Zeichenkette effektiv einnimmt (vor allem bei UTF-(7,8,16,32)).
Ich nehme wirklich an, dass varchar(255) gemeint wurde, denn text(255) wird zu text. Das scheint eine der zahlreichen Kompatibilitätsakzeptierungen von MySQL zu sein.

@threadi: Wer Tabellennamen generiert, braucht nicht zu escapen, da es sich hierbei nicht um eine an die Datenbank gesendete Zeichenkette handelt.

http://be.php.net/manual/en/function.mysql-db-query.php schrieb:
This function [mysql_db_query] has been DEPRECATED as of PHP 5.3.0. Relying on this feature is highly discouraged.
 
Zeichensatzfehler dürfte folgende Meldung erzeugen:

(Setzen eines illegalen UTF-8-Chars in einem Spaltennamen über eine UTF-8-kodierte Verbindung)

Code:
Invalid utf8 character string: 'ð'

Das ist \xF0 gerendert in ISO-8859-1, aber in der Form alleinstehend illegal in UTF-8, weil Bestandteil eines Multibyte-Characters.

Asterixus schrieb:
Wer Tabellennamen generiert, braucht nicht zu escapen, da es sich hierbei nicht um eine an die Datenbank gesendete Zeichenkette handelt.

Das ist ein guter Punkt, String-Escaping (also mit Anführungszeichen) wäre an der Stelle sogar falsch, weil Identifier gefragt sind. Stimmt.

Escapet werden muss aber dennoch, wenn der Identifier-String Leerzeichen oder sonstige Zeichen mit spezieller Bedeutung für SQL-Strings enthält (Klammern, Apostrophen, …). Zend_Db hat dafür sogar eine quoteIdentifier-Methode, die für MySQL mehr oder weniger das hier tut:

PHP:
    $identifier = '   `abc ( die katze "läuft" im \'schnee\'    `  ';
    
    $identifier = str_replace('`', '``', $identifier);

    // Whitespace at start/end is not allowed (?)
    $identifier = trim($identifier);

    $identifier = '`' . $identifier . '`';

Ich tippe im vorliegenden Fall auf Whitespace oder ein sonstiges spezielles Zeichen im Identifier-Namen.

Wer rumbasteln möchte:

PHP:
<?php

function connect($dsn, $user, $password)
{
    $options = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES `utf8`'
    );

    $pdo = new PDO($dsn, $user, $password, $options);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    return $pdo;
}

function delete(PDO $pdo)
{
    $pdo->query('DROP TABLE IF EXISTS `foo`');
}

function create(PDO $pdo)
{
    $identifier = '   `abc ( die katze "läuft" im \'schnee\'    `  ';
    
    $identifier = str_replace('`', '``', $identifier);

    // Whitespace at start/end is not allowed (?)
    $identifier = trim($identifier);

    $identifier = '`' . $identifier . '`';

    $q = "CREATE TABLE `foo` (
            `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
            " . $identifier . " VARCHAR( 255 ) NOT NULL
          ) ENGINE = InnoDB";

    $pdo->query($q);
}

error_reporting(-1);

$pdo = connect('mysql:dbname=tests;host=localhost', '', '');
delete($pdo);
create($pdo);
 
Wobei sich mir die Frage stellt, ob es tatsächlich technisch so tief geht oder ob der gesendete String (Query) nicht einfach nur syntaktisch falsch (weil nicht escaped) ist und somit Sonderzeichen-Mist produziert, den SQL nicht verarbeiten kann.

Natürlich sind die Infos wertvoll, aber ich bezweifle, dass das Problem so tief sitzt.
 
Hallo!
Noch eine Beobachtung:
Sonder- und Leerzeichen werden im Datensatz akzeptiert, da gibt es kein Problem.
Das Problem ist ein Sonder- Leerzeichen im Spaltenname!

Das text-Format habe ich gewählt, da ich mehr als 8000 Zeilen brauche, die, wie mir mySQL sagte, mit char nicht möglich sind.
Gibt es da bei varchar einen Unterschied?

Zu der Methode wie ich Variablen in einen String einbinde:
Im Galileo-Openbook steht es so, wie ich es mache und es funktioniert auch!


Also, ich versuche die ganze Sache noch mal mit einer Escape-Funktion, vielen Dank für den Tipp.

Viele Grüße!
 
Schon aus Prinzip und alter Gewohnheit ersetze ich Lerzeichen und Umlaute durch Unterstrich und "oe", "ae" etc.
 
Hallo noch mal,

mit mysql_real_escape_string kann ich alle Sonderzeichen richtig im Datensatz speichern und auch das Auslesen gibt kein Problem.
Vielen vielen Dank für den Tipp!

Allerdings tritt weiterhin der Fehler bei Spaltennamen auf, und Escapen soll man ja hier nicht.
D.h. ich kann dort sonst Nichts tun, außer Sonderzeichen, die Fehler verursachen, zu löschen oder eben durch andere Zeichen zu ersetzen?
 
Das hier sollte es für Spaltennamen tun.

PHP:
function escapeColumName($name)
{   
    $name = str_replace('`', '``', $name);
    $name = trim($name);
    $name = '`' . $name . '`';

    return $name;
}
 
mermshaus schrieb:
Ich habe eben etwas erfolglos versucht, herauszufinden, welche Zeichen in Spaltennamen erlaubt sind. Generell würde ich nicht empfehlen, Zeichen zu verwenden, die nicht in ASCII-7 liegen, aber offenbar sieht MySQL das nicht so strikt.

MySQL nutzt intern wohl ausschließlich Unicode (iirc UTF-16) und wandelt entsprechend um. Afaik gehen bedingt dadurch seit 5.1 auch Multibyte-Feldnamen, -Datenbanknamen, -Tabellennamen usw.

Habe auch einmal erfolglos danach gegoogled.
 
Hallo!
Ich benutze zum Eingeben die Escape-Funktion, die mermshaus gepostet hat.
Jetzt gibt es aber einen Fehler, wenn ich mit mysql_result aus einer Abfrage einen Wert lesen will, wobei der Feldname durch eine Abfrage erfolgte.
Hier gibt es wohl schon wieder Zeichensatzprobleme, im Browser kann ich jedoch keinen Fehler erkennen.

PHP:
$res = mysql_db_query("$Datenbank", "select * from $Tabelle");
$cl = mysql_db_query("$Datenbank", "show columns from $Tabelle");
$numcl = mysql_num_rows($cl);
for ($l=0; $l<$numcl; $l++){
   $Spalte = mysql_result($cl, $l, "Field");
   $txt = mysql_result($res, $i, "$Spalte");
   print $txt;
}

Könnt Ihr mir noch mal helfen?
 
Bei dem zweiten mysql_result hast Du $i geschrieben, vermutlich wolltest Du aber $l (kleine L) schreiben.
 
Fang bitte damit an, dass du die Syntax richtig verwendest:
PHP:
$res = mysql_db_query($Datenbank, "select * from ".$Tabelle);
Lass also bitte die Doublequotes um die Variablen weg.

Dann kann ich nirgends einen Hinweis finden, an welchem Feldnamen sich SQL nun wirklich stört, soll heissen, wir (oder auch nur ich) raten, weil Tabellenname und Feldnamen fehlen.

Mal abgesehen von dem Fehler mit dem i/l
 

Neueste Beiträge

Zurück
Oben