SET NAMES utf8 in MySQL?

110

Ich sehe oft etwas Ähnliches in PHP-Skripten, die MySQL verwenden

query("SET NAMES utf8");   

Ich musste dies noch nie für ein Projekt tun, daher habe ich ein paar grundlegende Fragen dazu.

  1. Wird dies nur mit PDO durchgeführt?
  2. Wenn es sich nicht um eine gU-spezifische Sache handelt, wozu dient sie dann? Mir ist klar, dass die Codierung für MySQL festgelegt wird, aber ich meine, ich musste sie nie verwenden. Warum sollte ich sie verwenden wollen?
JasonDavis
quelle
4
"SET NAMES utf8" sollte wegen SQL-Injection vermieden werden. Weitere Informationen finden Sie unter php.net/manual/en/mysqlinfo.concepts.charset.php.
masakielastic
3
@masakielastic Ich sehe nicht, wo die Einstellung 'set names utf8' eine Bedrohung für die SQL-Injection darstellt. Mit der richtigen MySQL-API, wo ist der Thread?
Breitband
3
Entschuldigung für meine Unfreundlichkeit. Siehe die Antwort von ircmaxell : stackoverflow.com/a/12118602/531320 Althogh "SET NAMES" hat kein Problem, solange UTF-8 verwendet wird. Die Möglichkeit, dass Sie in Zukunft GBK oder Big5 (Chinesisch) oder Shift_JIS (Japanisch) verwenden, ist unbestreitbar .
masakielastic

Antworten:

74

Es wird immer dann benötigt, wenn Sie Daten mit Zeichen an den Server senden möchten, die in reinem ASCII nicht dargestellt werden können, z. B. 'ñ' oder 'ö'.

Dies ist der Fall, wenn die MySQL-Instanz nicht so konfiguriert ist, dass standardmäßig eine UTF-8-Codierung von Clientverbindungen erwartet wird (viele sind abhängig von Ihrem Standort und Ihrer Plattform).

Lesen Sie http://www.joelonsoftware.com/articles/Unicode.html, falls Sie nicht wissen, wie Unicode funktioniert.

Lesen Sie, ob Sie "SET NAMES" verwenden möchten, um Alternativen zu SET NAMES anzuzeigen und worum es genau geht.

Vinko Vrsalovic
quelle
3
'ö' und 'ñ' sind ASCII-erweitert. Würdest du noch SET NAMES UTF8für sie brauchen ?
Tim
2
Ich habe festgestellt, dass ich oft utf8_decode ($ my_text) hinzufügen muss; in PHP, um spezielle UTF-8-Zeichen zu erhalten, die auf Websites ordnungsgemäß angezeigt werden, wenn die Daten von MySQL abgefragt wurden. Meine Tabellen und Spalten sind in MySQL auf UTF-8 festgelegt. Sollte dies also erforderlich sein?
NexusRex
1
@ Vinko Vrsalovic: Nicht unbedingt ... Ich hatte alle meine Dateien in utf8, aber mein vorheriger Hoster hat den mysql-Zeichensatz auf latin1 gesetzt und weil ich mysql nicht gesagt habe, dass ich Zeichen in utf8 sende (daher setze Namen utf8), hat er sie gespeichert im lateinischen Zeichensatz und alle meine speziellen Zeichen (slowenisch čšž) sahen aus, als wären sie von einem Auto überfahren worden - eine weitere Sache: Wenn Sie in phpmyadmin suchen, werden Sie keine Ergebnisse finden, weil ein č wie Å ist und so weiter
Erik Čerpnjak
Beachten Sie, dass hier auch der Zeichensatz angegeben wird, den der Server zum Zurücksenden von Ergebnissen an den Client verwenden soll. Er wird daher auch beim Empfang dieser Daten benötigt, z. B. mithilfe einer SELECTAnweisung.
Leopoldo Sanczyk
@ Tim. Es gibt nicht wirklich so etwas wie "Extended ASCII". Es gibt eine ganze Reihe verschiedener Codierungen, die alle als erweitertes ASCII bezeichnet werden können (jeder Einzelbyte-Zeichensatz, bei dem die erste Hälfte mit ASCII identisch ist, und es gibt viele davon).
TRiG
43

Aus dem Handbuch :

SET NAMES gibt an, welchen Zeichensatz der Client zum Senden von SQL-Anweisungen an den Server verwendet.

Ausgefeilter (und noch einmal unentgeltlich aus dem Handbuch ):

SET NAMES gibt an, welchen Zeichensatz der Client zum Senden von SQL-Anweisungen an den Server verwendet. Daher teilt SET NAMES 'cp1251' dem Server mit, "zukünftige eingehende Nachrichten von diesem Client befinden sich im Zeichensatz cp1251." Außerdem wird der Zeichensatz angegeben, den der Server zum Zurücksenden von Ergebnissen an den Client verwenden soll. (Beispielsweise wird angegeben, welcher Zeichensatz für Spaltenwerte verwendet werden soll, wenn Sie eine SELECT-Anweisung verwenden.)

karim79
quelle
6
Ich liebe dich. Habe gerade meinen Abend gemacht!
Karim79
34

Die richtige Codierung ist wirklich schwierig - es gibt zu viele Ebenen:

  • Browser
  • Seite
  • PHP
  • MySQL

Der SQL-Befehl "SET CHARSET utf8" von PHP stellt sicher, dass die Clientseite (PHP) die Daten in utf8 erhält, unabhängig davon, wie sie in der Datenbank gespeichert sind. Natürlich müssen sie zuerst korrekt gespeichert werden.

DDL-Definition vs. reale Daten

Die für eine Tabelle / Spalte definierte Codierung bedeutet nicht wirklich, dass sich die Daten in dieser Codierung befinden. Wenn Sie zufällig eine Tabelle definiert haben, die utf8jedoch als unterschiedliche Codierung gespeichert ist, behandelt MySQL sie als utf8und Sie haben Probleme. Das heißt, Sie müssen dies zuerst beheben.

Was zu überprüfen

Sie müssen überprüfen, welche Codierung der Datenfluss auf jeder Ebene ist.

  • Überprüfen Sie die HTTP-Header und -Header.
  • Überprüfen Sie, was im Text der Anfrage wirklich gesendet wurde.
  • Vergessen Sie nicht, dass MySQL fast überall codiert ist:
    • Datenbank
    • Tabellen
    • Säulen
    • Server als Ganzes
    • Kunde Stellen
      Sie sicher, dass überall der richtige ist.

Umwandlung

Wenn Sie z. B. Daten empfangen windows-1250und in speichern möchten utf-8, verwenden Sie diese SQL vor dem Speichern:

SET NAMES 'cp1250';

Wenn Sie Daten in DB als haben windows-1250und abrufen möchten utf8, verwenden Sie:

SET CHARSET 'utf8';

Noch ein paar Anmerkungen:

  • Verlassen Sie sich nicht auf zu "intelligente" Tools, um die Daten anzuzeigen. Zum Beispiel macht phpMyAdmin die Codierung wirklich schlecht (als ich es benutzte). Und es geht durch alle Schichten, so dass es schwer herauszufinden ist.
  • Außerdem hatte Internet Explorer ein wirklich dummes Verhalten, die Codierung basierend auf seltsamen Regeln zu "erraten".
  • Verwenden Sie einfache Editoren, in denen Sie die Codierung wechseln können. Ich empfehle MySQL Workbench.
Ondra Žižka
quelle
19

Diese Abfrage sollte vor der Abfrage geschrieben werden, die Daten in der Datenbank erstellt oder aktualisiert. Diese Abfrage sieht folgendermaßen aus:

mysql_query("set names 'utf8'");

Beachten Sie, dass Sie die Codierung, die Sie verwenden, in den Header schreiben sollten. Wenn Sie beispielsweise utf-8 verwenden, fügen Sie sie wie folgt in den Header ein, da sonst ein Problem mit Internet Explorer auftritt

Ihre Seite sieht also so aus

<html>
    <head>
        <title>page title</title>
        <meta charset="UTF-8" />   
    </head>
    <body>
    <?php
            mysql_query("set names 'utf8'");   
            $sql = "INSERT * FROM ..... ";  
            mysql_query($sql);
    ?>    

    </body>
</html>
Usama Sulaiman
quelle
8
Sie sollten nicht die PHP-MySQL-Bibliothek verwenden, sondern MySQLi oder PDO.
André Figueira
Tolle Antwort, danke für das Beispiel. Dies ist die einzige Antwort, die mir geholfen hat, zu visualisieren, was ich tun musste, und die mein Problem gelöst hat!
GTS Joe
1
Das letzte Tag sollte </ html> nicht <html> sein
GTS Joe
9

Die Lösung ist

 $conn->set_charset("utf8");
nurp
quelle
5

Verwenden Sie stattdessen die PHP-Funktion mysqli :: set_charset mysqli_set_charset, anstatt dies über eine SQL-Abfrage zu tun

Note:

This is the preferred way to change the charset. Using mysqli_query() to set it (such as SET NAMES utf8) is not recommended.

Weitere Informationen finden Sie im Abschnitt MySQL-Zeichensatzkonzepte.

von http://www.php.net/manual/en/mysqli.set-charset.php

user1783273
quelle
1

Danke @all!

nicht verwenden: query ("SET NAMES utf8"); Dies ist Setup-Zeug und keine Abfrage. Stellen Sie es richtig, nachdem eine Verbindung mit setCharset () (oder einer ähnlichen Methode) gestartet wurde.

ein kleines Ding in Parctice:

Status:

  • MySQL Server spricht standardmäßig Latin1
  • Ihre ganze App ist in utf8
  • Die Verbindung wird ohne zusätzliche Verbindung hergestellt (also: latin1) (keine SET NAMES utf8 ..., keine set_charset () Methode / Funktion)

Das Speichern und Lesen von Daten ist kein Problem, solange MySQL mit den Zeichen umgehen kann. Wenn Sie in die Datenbank schauen, werden Sie bereits sehen, dass es Mist darin gibt (zB phpmyadmin).

bis jetzt ist das kein problem! (falsch aber funktioniert oft (in europa)) ..

..wenn kein anderer Client / Programm oder eine geänderte Bibliothek, die ordnungsgemäß funktioniert, Daten liest / speichert. dann bist du in großen Schwierigkeiten!

user3162905
quelle
0

Nicht nur PDO. Wenn SQL wie '????' Symbole, Voreinstellung Ihres Zeichensatzes (hoffentlich UTF-8) wirklich empfohlen:

if (!$mysqli->set_charset("utf8")) 
 { printf("Can't set utf8: %s\n", $mysqli->error); }

oder über den Prozedurstil mysqli_set_charset($db,"utf8")

dmitry_podyachev
quelle