MySQL: codage de caractères utilisé par SELECT INTO?
j'essaie d'exporter des données à partir D'une base de données MySQL, mais des choses étranges et merveilleuses arrivent à unicode dans cette table.
je vais me concentrer sur un seul personnage, la gauche smartquote: "
quand j'utilise SELECT
à partir de la console, il est imprimé sans problème:
mysql> SELECT text FROM posts;
+-------+
| text |
+-------+
| “foo” |
+-------+
cela signifie que les données sont envoyées à mon terminal comme utf-8[0] (ce qui est correct).
cependant, quand j'utilise SELECT * FROM posts INTO OUTFILE '/tmp/x.csv' …;
le fichier de sortie est correctement codé:
$ cat /tmp/x.csv
“fooâ€
plus Précisément, le “
est codé avec sept (7!) octets: xc3xa2xe2x82xacxc5x93
.
Quel encodage est-ce? Ou comment pourrais-je dire à MySQL d'utiliser un encodage moins déraisonnable?
en outre, quelques faits divers:
SELECT @@character_set_database
retournelatin1
text
la colonne est unVARCHAR(42)
:“
utf-8, les rendementsxe2x80x9c
xe2x80x9c
décodé commelatin1
puis ré-encodé commeutf-8
les rendementsxc3xa2xc2x80xc2x9c
(6 octets).- un Autre point de données:
…
(utf-8:xe2x80xa6
) est codéxc3xa2xe2x82xacxc2xa6
[0]: comme les guillemets intelligents ne sont inclus dans aucun encodage 8 bits, et mon terminal rend correctement les caractères utf-8.
8 réponses
de nombreux programmes / normes (y compris MySQL) supposent que "latin1" signifie "cp1252", de sorte que l'octet 0x80 est interprété comme un symbole Euro, ce qui est où \xe2\x82\xac
bit (U+20AC) vient du milieu.
quand j'essaie ceci, cela fonctionne correctement (mais notez comment je mets les données, et les variables sur le serveur de base de données):
mysql> set names utf8; -- http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html
mysql> create table sq (c varchar(10)) character set utf8;
mysql> show create table sq\G
*************************** 1. row ***************************
Table: sq
Create Table: CREATE TABLE `sq` (
`c` varchar(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.19 sec)
mysql> insert into sq values (unhex('E2809C'));
Query OK, 1 row affected (0.00 sec)
mysql> select hex(c), c from sq;
+--------+------+
| hex(c) | c |
+--------+------+
| E2809C | “ |
+--------+------+
1 row in set (0.00 sec)
mysql> select * from sq into outfile '/tmp/x.csv';
Query OK, 1 row affected (0.02 sec)
mysql> show variables like "%char%";
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
Et à partir du shell:
/tmp$ hexdump -C x.csv
00000000 e2 80 9c 0a |....|
00000004
j'espère qu'il y est une friandise utile...
Les nouvelles versions de MySQL ont une option pour définir le jeu de caractères dans la clause outfile:
SELECT col1,col2,col3
FROM table1
INTO OUTFILE '/tmp/out.txt'
CHARACTER SET utf8
FIELDS TERMINATED BY ','
Pour répondre spécifiquement à votre question "qu'est-Ce que cela?", vous avez répondu vous-même:
je soupçonne que c'est parce que "les valeurs de colonne sont évaluées en utilisant le jeu de caractères binaires. En effet, il n'y a pas de conversion de jeu de caractères."- dev.mysql.com/doc/refman/5.0/en/select-into.html
C'est la façon dont MySQL stocke utf8
données codées en interne. C'est une variation terriblement inefficace du stockage Unicode, apparemment en utilisant un total de trois octets pour la plupart des caractères, et ne supporte pas quatre séquences de octets UTF-8.
comment le convertir en UTF-8 réel en utilisant INTO OUTFILE
... Je ne sais pas. Utilisation d'autres mysqldump
les méthodes le feront cependant.
comme vous pouvez voir ma base de données MySQL utiliser utf-8.
mysql> SHOW VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
+--------------------------+--------+
7 rows in set (0.00 sec)
chaque fois que j'ai essayé d'exporter la table, j'ai eu un étrange fichier codé CSV. Alors, j'ai mis:
mysql_query("SET NAMES CP1252");
header('Content-Type: text/csv; charset=cp1252');
header('Content-Disposition: attachment;filename=output.csv');
comme dans mon exporter script.
alors J'ai une sortie UTF-8 pure.
j'ai trouvé que cela fonctionne bien.
SELECT convert(col_name USING latin1) FROM posts INTO OUTFILE '/tmp/x.csv' …;
SET CHARACTER SET <blah>
avant votre select, <blah>=utf8
ou latin1
etc...
Voir: http://dev.mysql.com/doc/refman/5.6/en/charset-connection.html
Ou SET NAMES utf8;
ça pourrait marcher...
vous pouvez exécuter des requêtes MySQL en utilisant L'outil CLI (je crois même avec un format de sortie pour qu'il imprime CSV) et rediriger vers un fichier. Devrait faire la conversion de charset et tout de même vous donner accès à faire jointures, etc.
Vous devez émettre charset utf8
à L'invite MySQL avant d'exécuter le SELECT
. Cela indique au serveur sous quoi afficher les résultats.