web-dev-qa-db-fra.com

Est-ce que "définir le jeu de caractères UTF8" est nécessaire?

Je regrette notre classe de base de données (PDO basée) et je suis resté bloqué à cela. On m'a appris à utiliser SET NAMES utf8 et SET CHARACTER SET utf8 Lorsque vous travaillez avec UTF-8 In PHP et MySQL.

En PDO je veux maintenant utiliser le PDO::MYSQL_ATTR_INIT_COMMAND Paramètre, mais il ne prend en charge que une requête.

Est SET CHARACTER SET utf8 nécessaire?

30
Znarkus

À l'aide de SET CHARACTER SET utf8 après avoir utilisé SET NAMES utf8 réinitialisera réellement le character_set_connection et collation_connection à
[.____] @@character_set_database et @@collation_database respectivement.

Le manuel indique que

  • SET NAMES x est équivalent à

    SET character_set_client = x;
    SET character_set_results = x;
    SET character_set_connection = x;
    
  • et SET CHARACTER SET x est équivalent à

    SET character_set_client = x;
    SET character_set_results = x;
    SET collation_connection = @@collation_database;
    

tandis que SET collation_connection = x aussi interne exécute SET character_set_connection = <<character_set_of_collation_x>> et SET character_set_connection = x interne également exécute SET collation_connection = <<default_collation_of_character_set_x.

Donc essentiellement que vous réinitialisez character_set_connection à @@character_set_database et collation_connection à @@collation_database. Le manuel explique l'utilisation de ces variables:

Quel jeu de caractères doit-il traduire une instruction après la réception ?

Pour cela, le serveur utilise les variables système_set_connection et Collation_Connection. Il convertit des instructions envoyées par le client de caractères_set_client en caractères_set_connection (à l'exception des littéraux de chaîne qui ont un introducteur tel que _Latin1 ou _UTF8). Collation_Connection est important pour les comparaisons de chaînes littérales. Pour des comparaisons de chaînes avec des valeurs de colonne, Collation_Connection n'a pas d'importance car les colonnes ont leur propre collation, ce qui a une priorité de classement plus élevée.

Pour résumer cela, la procédure de codage/transcodage MySQL utilise pour traiter la requête et ses résultats sont une chose multi-pas-chose:

  1. MySQL traite la requête entrante comme codée dans character_set_client.
  2. MySQL transcode la déclaration de character_set_client dans character_set_connection
  3. lors de la comparaison des valeurs de chaîne aux valeurs de colonne, MySQL transcoque la valeur de la chaîne de character_set_connection Dans le jeu de caractères de la colonne de base de données donnée et utilise la collecte de colonne pour le tri et la comparaison.
  4. MySQL construit le jeu de résultats codé dans character_set_results (cela inclut les données de résultat ainsi que des métadonnées de résultat tels que les noms de colonne, etc.)

Donc, cela pourrait être le cas qu'un SET CHARACTER SET utf8 ne serait pas suffisant pour fournir un soutien complet UTF-8. Pensez à un ensemble de caractères de base de données par défaut de latin1 et colonnes définies avec utf8- Charset et traversez les étapes décrites ci-dessus. Comme latin1 Impossible de couvrir tous les caractères que UTF-8 peut couvrir Vous pouvez perdre des informations de caractère dans STEP 3.

  • Étape 3: Étant donné que votre requête est codée dans UTF-8 et contient des caractères qui ne peuvent pas être représentés avec latin1, ces personnages seront perdus sur le transcodage de utf8 à latin1 (le jeu de caractères de la base de données par défaut) rendant votre requête échoue.

Donc, je pense qu'il est prudent de dire que SET NAMES ... est la bonne façon de gérer les problèmes de jeu de caractères. Même si j'ajouterais peut-être correctement la configuration de vos variables de serveur MySQL (toutes les variables requises peuvent être définies statiquement dans votre my.cnf) vous libère de la surcharge de performance de la requête supplémentaire requise sur chaque connexion.

86
Stefan Gehrig

Du Manuel MySQL :

Définir le jeu de caractères est similaire aux noms défini mais définit character_set_connection et collation_connection à character_set_database et collation_database. UNE SET CHARACTER SET x La déclaration est équivalente à ces trois déclarations:

SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;
2
soulmerge

Depuis que vous deviez prendre en charge les ensembles de caractères internationaux, j'ai toujours simplement défini le jeu de caractères des champs Type de texte sur la création de la base de données.

J'ai aussi toujours utilisé UTF-8.

Dans PHP set identique:

mb_internal_encoding( 'UTF-8' );
0
Daren Schwenke