¿ESTABLECER NOMBRES utf8 en MySQL?

110

A menudo veo algo similar a esto a continuación en los scripts PHP que usan MySQL

query("SET NAMES utf8");   

Nunca he tenido que hacer esto para ningún proyecto, así que tengo un par de preguntas básicas al respecto.

  1. ¿Es esto algo que se hace solo con DOP?
  2. Si no es una cosa específica de DOP, ¿cuál es el propósito de hacerlo? Me doy cuenta de que está configurando la codificación para mysql, pero quiero decir, nunca he tenido que usarlo, así que ¿por qué querría usarlo?
JasonDavis
fuente
4
"SET NAMES utf8" debe evitarse debido a la inyección SQL. Consulte php.net/manual/en/mysqlinfo.concepts.charset.php para obtener más detalles.
masakielastic
3
@masakielastic No veo dónde la configuración de 'establecer nombres utf8' es una amenaza para la inyección SQL? Usando la API de MySQL adecuada, ¿dónde está el hilo?
banda ancha
3
Perdón por mi crueldad. Vea la respuesta de ircmaxell: stackoverflow.com/a/12118602/531320 Aunque "SET NAMES" no tiene ningún problema siempre que use UTF-8, la posibilidad de que use GBK o Big5 (chino) o Shift_JIS (japonés) en el futuro es innegable .
masakielastic

Respuestas:

74

Es necesario siempre que desee enviar datos al servidor con caracteres que no se pueden representar en ASCII puro, como 'ñ' o 'ö'.

Eso si la instancia de MySQL no está configurada para esperar la codificación UTF-8 de forma predeterminada de las conexiones del cliente (muchas lo están, según su ubicación y plataforma).

Lea http://www.joelonsoftware.com/articles/Unicode.html en caso de que no sepa cómo funciona Unicode.

Lea si usar "SET NAMES" para ver las alternativas de SET NAMES y de qué se trata exactamente.

Vinko Vrsalovic
fuente
3
'ö' y 'ñ' son ASCII extendidos. ¿Todavía lo necesitarías SET NAMES UTF8para ellos?
Tim
2
Descubrí que a menudo tengo que agregar utf8_decode ($ my_text); en PHP para obtener caracteres especiales UTF-8 para que se muestren correctamente en los sitios web cuando los datos se consultaron desde MySQL. Mis tablas y columnas están configuradas en UTF-8 en MySQL, ¿debería ser necesario?
NexusRex
1
@ Vinko Vrsalovic: No necesariamente ... Tenía todos mis archivos en utf8 pero mi proveedor anterior tenía el conjunto de caracteres mysql configurado en latin1 y como no le he dicho a mysql que estoy enviando caracteres en utf8 (por lo tanto, establezca los nombres utf8), los almacenó en el conjunto de caracteres latinos y todos mis caracteres especiales (čšž esloveno) parecían invadidos por un coche - una cosa más: cuando haces una búsqueda en phpmyadmin no encontrarás resultados, porque un č es como Å y así sucesivamente
Erik Čerpnjak
Tenga en cuenta que también especifica el conjunto de caracteres que el servidor debe usar para enviar los resultados al cliente, por lo que también es necesario al recibir estos datos, usando por ejemplo una SELECTdeclaración.
Leopoldo Sanczyk
@Tim. Realmente no existe tal cosa como "ASCII extendido". Hay un montón de codificaciones diferentes que pueden llamarse ASCII extendido (cualquier conjunto de caracteres de un solo byte donde la primera mitad es igual que ASCII, y hay muchos de esos).
TRiG
43

Del manual :

SET NAMES indica qué juego de caracteres utilizará el cliente para enviar sentencias SQL al servidor.

De manera más elaborada (y una vez más, extraída gratuitamente del manual ):

SET NAMES indica qué juego de caracteres utilizará el cliente para enviar sentencias SQL al servidor. Por lo tanto, SET NAMES 'cp1251' le dice al servidor, "los futuros mensajes entrantes de este cliente están en el juego de caracteres cp1251". También especifica el conjunto de caracteres que el servidor debe usar para enviar los resultados al cliente. (Por ejemplo, indica qué juego de caracteres usar para los valores de columna si usa una instrucción SELECT).

karim79
fuente
6
te quiero. ¡Acabo de hacer mi noche!
karim79
34

Obtener la codificación correcta es realmente complicado: hay demasiadas capas:

  • Navegador
  • Página
  • PHP
  • MySQL

El comando SQL "SET CHARSET utf8" de PHP asegurará que el lado del cliente (PHP) obtendrá los datos en utf8, sin importar cómo estén almacenados en la base de datos. Por supuesto, primero deben almacenarse correctamente.

Definición de DDL frente a datos reales

La codificación definida para una tabla / columna no significa realmente que los datos estén en esa codificación. Si tiene una tabla definida como utf8pero almacenada con una codificación diferente, entonces MySQL las tratará como utf8si estuviera en problemas. Lo que significa que tienes que arreglar esto primero.

Que comprobar

Debe verificar qué codifica el flujo de datos en cada capa.

  • Compruebe los encabezados HTTP, encabezados.
  • Verifique lo que realmente se envió en el cuerpo de la solicitud.
  • No olvide que MySQL tiene codificación en casi todas partes:
    • Base de datos
    • Mesas
    • Columnas
    • Servidor en su conjunto
    • Cliente
      Asegúrese de que haya el correcto en todas partes.

Conversión

Si recibe datos en windows-1250, por ejemplo , y desea almacenarlos utf-8, utilice este SQL antes de almacenar:

SET NAMES 'cp1250';

Si tiene datos en la base de datos windows-1250y desea recuperarlos utf8, use:

SET CHARSET 'utf8';

Algunas notas más:

  • No confíe en herramientas demasiado "inteligentes" para mostrar los datos. Por ejemplo, phpMyAdmin hace (estaba haciendo cuando lo estaba usando) codificación realmente mala. Y pasa por todas las capas, por lo que es difícil de averiguar.
  • Además, Internet Explorer tuvo un comportamiento realmente estúpido al "adivinar" la codificación basándose en reglas extrañas.
  • Utilice editores sencillos en los que pueda cambiar la codificación. Recomiendo MySQL Workbench.
Ondra Žižka
fuente
19

Esta consulta debe escribirse antes de la consulta que crea o actualiza datos en la base de datos, esta consulta se ve así:

mysql_query("set names 'utf8'");

Tenga en cuenta que debe escribir la codificación que está usando en el encabezado, por ejemplo, si está usando utf-8, lo agrega así en el encabezado o surgirá un problema con Internet Explorer

para que tu página se vea así

<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
fuente
8
No debería utilizar la biblioteca PHP mysql, en su lugar debería utilizar MySQLi o PDO.
André Figueira
Gran respuesta, gracias por el ejemplo. ¡Esta es la única respuesta que me ayudó a visualizar lo que tenía que hacer y resolvió mi problema!
GTS Joe
1
La última etiqueta debe ser </html> no <html>
GTS Joe
9

La solucion es

 $conn->set_charset("utf8");
Nurp
fuente
5

En lugar de hacer esto a través de una consulta SQL, use la función 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.

Consulte la sección de conceptos del juego de caracteres MySQL para obtener más información.

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

usuario1783273
fuente
1

¡Gracias a todos!

no use: query ("SET NAMES utf8"); esto es algo de configuración y no una consulta. ponerlo justo después de iniciar una conexión con setCharset () (o un método similar)

alguna cosita en parctice:

estado:

  • servidor mysql por defecto habla latin1
  • tu aplicación de agujero está en utf8
  • la conexión se realiza sin ningún extra (entonces: latin1) (sin SET NAMES utf8 ..., sin método / función set_charset ())

Almacenar y leer datos no es un problema siempre que mysql pueda manejar los caracteres. si miras en la base de datos ya verás que hay basura en ella (por ejemplo, usando phpmyadmin).

hasta ahora esto no es un problema! (incorrecto pero funciona a menudo (en europa)) ..

.. a menos que otro cliente / programa o una biblioteca modificada, que funcione correctamente, lea / guarde los datos. ¡entonces estás en un gran problema!

usuario3162905
fuente
0

No solo DOP. Si sql responde como '????' símbolos, preestablecido de su juego de caracteres (espero que UTF-8) realmente recomendado:

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

o mediante estilo de procedimiento mysqli_set_charset($db,"utf8")

dmitry_podyachev
fuente