Ver Mensaje Individual
  #1 (permalink)  
Antiguo 16/09/2013, 13:18
Pantaláimon
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 17 años, 10 meses
Puntos: 32
comportamiento inesperado utf8_spanish_ci

Buenas.

Mirando sobre el tema de los character sets y collations he leído que en mysql collation utf8_spanish_ci no distingue entre vocales con tilde o sin tilde. Sin embargo, a mi me está ocurriendo lo contrario y me gustaría averiguar por qué. Así que os presento un pequeño código que he hecho para intentar descubrir por qué razón no se comporta adecuadamente.

Primeramente quería recordar que en utf8 el carácter "o" equivale a x6F o 111 y el carácter "ó" equivale a xc3 b3 o 195 179.

Bien, pues el código que voy a exponer trata de insertar en una tabla el texto "camión"(con tilde) y luego comprobar si existe alguna palabra en la tabla que contenga "camion"(sin tilde)

Para ello he creado la base de datos asignándole el character set y collation:
Código MySQL:
Ver original
  1. create database if not exists dbase character set utf8 collate utf8_spanish_ci;
Luego creo la tabla de nombre texto:
Código MySQL:
Ver original
  1. create table dbase.texto ( texto varchar(10) not null );
Creo privilegios para esa base de datos para un usuario de nombre "user" y contraseña "1234":
Código MySQL:
Ver original
  1. grant all on dbase.* to 'user'@'%' identified by '1234';

Luego creo el código php y lo guardo en formato utf-8:
Código PHP:
<?php

    
function connect_db()
    {
        
$db_link = new mysqli"localhost""user""1234""dbase" );
        
// comprobar que la conexión se efectúe
        
if( $db_link->connect_errno )
        {
            echo 
"Conexion fallida: ".$db_link->connect_error;
            exit();
        }
        return 
$db_link;
    }

    function 
select$texto )
    {
        
$db_link connect_db();

        
$result 
            
$db_link->query
                
"select * from dbase.texto where texto like '%".addslashes($texto).
                
"%' " 
            
);

        
// comprobar que la consulta se efectúe
        
if( $result === false )
        {
            echo 
"select error: ".$db_link->error "<br/>";
            exit();
        }

        
// si la seleccion no es vacia, guardar el primer elemento
        
if( $result->num_rows )
        {
            
$row  $result->fetch_assoc();
            
$word $row["texto"];
        }
        
// en caso contrario guardar false
        
else
            
$word  false;
        
$db_link->close();
        
//retornar el valor
        
return $word;
    }

    function 
insert$texto )
    {
        
$db_link connect_db();

        
$result $db_link->query"insert into dbase.texto values('".$texto."')" );

        
// comprobar que la inserción se efectúe
        
if( $result === false )
        {
            echo 
"insert error: " $db_link->error "<br/>";
            exit();
        }

        
$db_link->close();

    }


    
//-------------------------

    
header('Content-Type: text/html; charset=UTF-8');

    
// insertar camión(con acento) en base de datos
    
insert"camión" );

    
// mostrar palabra camion(sin acento) y su codigo
    
$word "camion";
    echo 
"palabra buscada: $word<br/>codigo: ";
    
$len strlen$word );
    for( 
$i 0$i $len; ++$i )
        echo 
ord$word[$i] ) . " ";
    echo 
"<br/><br/>";

    
// buscar palabra en la base de datos
    
$texto select$word );

    
// Si se encuentra la palabra, mostrarla
    
if( $texto !== false )
    {
        echo 
"Palabra encontrada: \"" $texto "\"<br/>código: ";

        
$len strlen$texto );
        for( 
$i 0$i $len; ++$i )
            echo 
ord$texto[$i] ) . " ";
    }
    else
    {
        echo 
"Palabra no encontrada";
    }

?>
Pues bien, al ejecutar este código, como decía al inicio, no encuentra la palabra "camión", que en principio debería ser equivalente a "camion".

Código:
La salida es la siguiente:
palabra buscada: camion
codigo: 99 97 109 105 111 110 

Palabra no encontrada
Sin embargo, si cambio la linea:
Código PHP:
    $word "camion"
por
Código PHP:
    $word "camión"
Si me encuentra la palabra y la salida es:
Código:
palabra buscada: camión
codigo: 99 97 109 105 195 179 110 

Palabra encontrada: "camión"
código: 99 97 109 105 195 179 110
Como se puede apreciar, tanto la palabra de búsqueda como la que está insertada en la base de datos estan en utf-8. Pues se puede apreciar la secuencia 195 179 correspondiente al código de "ó" en utf-8.

¿Qué está pasando entonces?

Un saludo y gracias!