FIXER LES NOMS utf8 dans MySQL?

110

Je vois souvent quelque chose de similaire ci-dessous dans les scripts PHP utilisant MySQL

query("SET NAMES utf8");   

Je n'ai encore jamais eu à faire cela pour aucun projet, alors j'ai quelques questions de base à ce sujet.

  1. Est-ce quelque chose qui se fait uniquement avec PDO?
  2. Si ce n'est pas une chose spécifique à une AOP, quel est le but de le faire? Je me rends compte que c'est le réglage de l'encodage pour mysql mais je veux dire, je n'ai jamais eu à l'utiliser, alors pourquoi voudrais-je l'utiliser?
JasonDavis
la source
4
"SET NAMES utf8" doit être évité en raison de l'injection SQL. Voir php.net/manual/en/mysqlinfo.concepts.charset.php pour plus de détails.
masakielastic
3
@masakielastic Je ne vois pas où définir 'set names utf8' est une menace pour l'injection SQL? En utilisant l'API MySQL appropriée, où est le fil?
haut débit
3
Désolé pour ma méchanceté. Voir la réponse d'ircmaxell: stackoverflow.com/a/12118602/531320 Althogh "SET NAMES" n'a aucun problème tant que vous utilisez UTF-8, la possibilité que vous utilisiez GBK ou Big5 (chinois) ou Shift_JIS (japonais) à l'avenir est indéniable .
masakielastic

Réponses:

74

Il est nécessaire chaque fois que vous souhaitez envoyer des données au serveur ayant des caractères qui ne peuvent pas être représentés en ASCII pur, comme «ñ» ou «ö».

Que si l'instance MySQL n'est pas configurée pour s'attendre à un encodage UTF-8 par défaut à partir des connexions client (beaucoup le sont, en fonction de votre emplacement et de votre plate-forme.)

Lisez http://www.joelonsoftware.com/articles/Unicode.html au cas où vous ne sauriez pas comment fonctionne Unicode.

Lisez S'il faut utiliser "SET NAMES" pour voir les alternatives de SET NAMES et de quoi il s'agit exactement.

Vinko Vrsalovic
la source
3
'ö' et 'ñ' sont de l'ASCII étendu. En auriez-vous encore besoin SET NAMES UTF8pour eux?
Tim
2
J'ai constaté que je dois souvent ajouter utf8_decode ($ my_text); en PHP pour obtenir des caractères UTF-8 spéciaux à afficher correctement sur les sites Web lorsque les données ont été interrogées à partir de MySQL. Mes tables et colonnes sont définies sur UTF-8 dans MySQL. Cela devrait-il donc être nécessaire?
NexusRex
1
@ Vinko Vrsalovic: Pas nécessairement ... j'avais tous mes fichiers dans utf8 mais mon hébergeur précédent avait le jeu de caractères mysql réglé sur latin1 et parce que je n'ai pas dit à mysql que j'envoyais des caractères en utf8 (d'où les noms de jeu utf8), il les a stockés en latin charset et tous mes caractères spéciaux (slovène čšž) semblaient avoir été envahis par une voiture - une dernière chose: lorsque vous faites une recherche dans phpmyadmin, vous ne trouverez pas de résultats, car un č est comme Å et ainsi de suite
Erik Čerpnjak
Notez qu'il spécifie également le jeu de caractères que le serveur doit utiliser pour renvoyer les résultats au client, il est donc également nécessaire lors de la réception de ces données, en utilisant par exemple une SELECTinstruction.
Leopoldo Sanczyk
@Tim. Il n'y a pas vraiment de "ASCII étendu". Il existe tout un tas d'encodages différents qui peuvent tous être appelés ASCII étendu (tout jeu de caractères à un octet où la première moitié est identique à ASCII, et il y en a beaucoup).
TRiG le
43

À partir du manuel :

SET NAMES indique le jeu de caractères que le client utilisera pour envoyer des instructions SQL au serveur.

De manière plus élaborée, (et encore une fois, gratuitement retirée du manuel ):

SET NAMES indique le jeu de caractères que le client utilisera pour envoyer des instructions SQL au serveur. Ainsi, SET NAMES 'cp1251' indique au serveur, "les futurs messages entrants de ce client sont dans le jeu de caractères cp1251." Il spécifie également le jeu de caractères que le serveur doit utiliser pour renvoyer les résultats au client. (Par exemple, il indique le jeu de caractères à utiliser pour les valeurs de colonne si vous utilisez une instruction SELECT.)

karim79
la source
6
Je t'aime. Je viens de faire ma soirée!
karim79
34

Obtenir le bon encodage est vraiment délicat - il y a trop de couches:

  • Navigateur
  • Page
  • PHP
  • MySQL

La commande SQL "SET CHARSET utf8" de PHP garantira que le côté client (PHP) obtiendra les données dans utf8, peu importe comment elles sont stockées dans la base de données. Bien sûr, ils doivent d'abord être stockés correctement.

Définition DDL vs données réelles

L'encodage défini pour une table / colonne ne signifie pas vraiment que les données sont dans cet encodage. Si vous aviez une table définie comme utf8mais stockée sous un encodage différent, MySQL les traitera comme utf8et vous avez des problèmes. Ce qui signifie que vous devez d'abord résoudre ce problème.

Que vérifier

Vous devez vérifier le codage du flux de données à chaque couche.

  • Vérifiez les en-têtes HTTP, les en-têtes.
  • Vérifiez ce qui est réellement envoyé dans le corps de la demande.
  • N'oubliez pas que MySQL a un encodage presque partout:
    • Base de données
    • les tables
    • Colonnes
    • Serveur dans son ensemble
    • Client
      Assurez-vous qu'il y a le bon partout.

Conversion

Si vous recevez des données par exemple windows-1250, et que vous souhaitez stocker utf-8, utilisez ce SQL avant de stocker:

SET NAMES 'cp1250';

Si vous avez des données dans la base de données windows-1250et que vous souhaitez les récupérer utf8, utilisez:

SET CHARSET 'utf8';

Quelques notes de plus:

  • Ne comptez pas sur des outils trop «intelligents» pour afficher les données. Par exemple, phpMyAdmin fait (faisait quand je l'utilisais) un encodage vraiment mauvais. Et cela traverse toutes les couches, donc c'est difficile à découvrir.
  • En outre, Internet Explorer avait un comportement vraiment stupide de "deviner" l'encodage basé sur des règles étranges.
  • Utilisez des éditeurs simples où vous pouvez changer de codage. Je recommande MySQL Workbench.
Ondra Žižka
la source
19

Cette requête doit être écrite avant la requête qui crée ou met à jour des données dans la base de données, cette requête ressemble à:

mysql_query("set names 'utf8'");

Notez que vous devez écrire l'encodage que vous utilisez dans l'en-tête, par exemple si vous utilisez utf-8, vous l'ajoutez comme ceci dans l'en-tête ou cela causera un problème avec Internet Explorer

donc votre page ressemble à ceci

<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
la source
8
Vous ne devriez pas utiliser la bibliothèque PHP mysql à la place, vous devriez utiliser MySQLi ou PDO.
André Figueira
Excellente réponse, merci pour l'exemple. C'est la seule réponse qui m'a aidé à visualiser ce que je devais faire et qui a résolu mon problème!
GTS Joe
1
La dernière balise doit être </html> pas <html>
GTS Joe
9

La solution est

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

Au lieu de le faire via une requête SQL, utilisez la fonction php: mysqli :: set_charset mysqli_set_charset

Note:

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

Consultez la section sur les concepts du jeu de caractères MySQL pour plus d'informations.

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

user1783273
la source
1

Merci a tous!

ne pas utiliser: query ("SET NAMES utf8"); il s'agit de trucs de configuration et non d'une requête. mettez-le juste après un début de connexion avec setCharset () (ou une méthode similaire)

une petite chose en parctice:

statut:

  • le serveur mysql par défaut parle latin1
  • votre application de trou est dans utf8
  • la connexion se fait sans aucun supplément (donc: latin1) (pas de SET NAMES utf8 ..., pas de méthode / fonction set_charset ())

Stocker et lire les données ne pose aucun problème tant que mysql peut gérer les caractères. si vous regardez dans la base de données, vous verrez déjà qu'il y a de la merde dedans (par exemple en utilisant phpmyadmin).

jusqu'à présent, ce n'est pas un problème! (faux mais fonctionne souvent (en Europe)) ..

..à moins qu'un autre client / programme ou une bibliothèque modifiée, qui fonctionne correctement, lira / enregistrera les données. alors vous avez de gros ennuis!

user3162905
la source
0

Pas seulement AOP. Si sql répond comme '????' symboles, prédéfini de votre jeu de caractères (espérons UTF-8) vraiment recommandé:

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

ou via le style de procédure mysqli_set_charset($db,"utf8")

dmitry_podyachev
la source