Saltar al contenido

¿Cuál es el impacto de LC_CTYPE en una base de datos PostgreSQL?

Deseamos mostrarte la mejor solución que hemos encontrado por todo internet. Queremos que te sea útil y si quieres aportar cualquier detalle que nos pueda ayudar a mejorar hazlo con total libertad.

Solución:

¿Cuáles son las desventajas de usar LC_CTYPE=’C’ sobre una localización específica?

La documentación menciona la relación entre las configuraciones regionales y las características de SQL en Soporte de configuraciones regionales:

La configuración regional influye en las siguientes características de SQL:

  • Ordenar el orden en consultas usando ORDER BY o los operadores de comparación estándar en datos textuales

  • Las funciones superior, inferior e initcap

  • Operadores de coincidencia de patrones (LIKE, SIMILAR TO y expresiones regulares de estilo POSIX); las configuraciones regionales afectan tanto a la coincidencia que no distingue entre mayúsculas y minúsculas como a la clasificación de caracteres mediante expresiones regulares de clase de carácter

  • La familia de funciones to_char

  • La capacidad de usar índices con cláusulas LIKE

El primer elemento (orden de clasificación) se trata de LC_COLLATE y los demás parecen ser todos sobre LC_CTYPE.

LC_COLLATE

LC_COLLATE Afecta a las comparaciones entre cadenas. En la práctica, el efecto más visible es el orden de clasificación. LC_COLLATE='C' (o POSIX que es un sinónimo) significa que es el orden de bytes lo que impulsa las comparaciones, mientras que una configuración regional en el language_REGION forma significa que las reglas culturales impulsarán las comparaciones.

Un ejemplo con nombres en francés, ejecutado desde dentro de una base de datos UTF-8:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
 AS l(firstname)
order by firstname collate "fr_FR";

Resultado:

 firstname 
-----------
 béatrice
 bérénice
 bernard
 boris

béatrice viene antes boris, porque la E acentuada se compara con la O como si no estuviera acentuada. Es una regla cultural.

Esto difiere de lo que sucede con un C lugar:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris')) 
 AS l(firstname)
order by firstname collate "C";

Resultado:

 firstname 
-----------
 bernard
 boris
 béatrice
 bérénice

Ahora los nombres con E acentuada se colocan al final de la lista. La representación de bytes de é en UTF-8 es el hexadecimal C3 A9 y para o es 6f. c3 es mayor que 6f así que bajo el C lugar, 'béatrice' > 'boris'.

No son solo los acentos. Hay reglas más complejas con guiones, puntuación y caracteres extraños como œ. Se esperan reglas culturales extrañas en todos los lugares.

Ahora bien, si las cadenas para comparar mezclan diferentes idiomas, como cuando se tiene un firstname columna para personas de todo el resto del mundo, podría ser que un lugar en particular no debería dominar, de todos modos, porque los diferentes alfabetos para diferentes idiomas no se han diseñado para clasificarse entre sí.

En este caso C es una elección racional y tiene la ventaja de ser más rápido, porque nada puede superar las comparaciones de bytes puros.

LC_CTYPE

Tener LC_CTYPE establecido en ‘C’ implica que C funciona como isupper(c) o tolower(c) proporcione los resultados esperados solo para caracteres en el rango US-ASCII (es decir, hasta el punto de código 0x7F en Unicode).

Debido a que SQL funciona como upper(), lower() o initcap
se implementan en Postgres además de estas funciones libc, se ven afectadas por esto tan pronto como haya caracteres que no sean US-ASCII en las cadenas.

Ejemplo:

test=> show lc_ctype;
  lc_ctype   
-------------
 fr_FR.UTF-8
(1 row)

-- Good result
test=> select initcap('élysée');
 initcap 
---------
 Élysée
(1 row)

-- Wrong result
-- collate "C" is the same as if the db has been created with lc_ctype='C'
test=> select initcap('élysée' collate "C");
 initcap 
---------
 éLyséE
(1 row)

Para el C lugar, é es tratado como un personaje no categorizable.

Del mismo modo, también se obtienen resultados erróneos con expresiones regulares:

test=> select 'élysée' ~ '^w+$';
 ?column? 
----------
 t
(1 row)

test=> select 'élysée' COLLATE "C" ~ '^w+$';
 ?column? 
----------
 f
(1 row)

En referencia a la respuesta aceptada de Daniel sobre la clasificación mediante intercalaciones, tenga en cuenta que si está ejecutando PostgreSQL en una Mac, es posible que su intercalación preferida no funcione como espera debido a configuraciones inadecuadas para algunas intercalaciones en el nivel del sistema operativo. Puedes leer más sobre el tema aquí:

http://www.postgresql.org/message-id/[email protected]

Este no es un problema específico de PostgreSQL, sino más bien un problema con la configuración predeterminada de Mac para la configuración de intercalación. Mi sistema actual ejecuta PostgreSQL 9.3 en OS X El Capitan versión 10.11 y sufre este problema. Mi sistema devuelve los mismos resultados de consulta independientemente de si uso la intercalación “fr_FR” o “en_US”. Por ejemplo:

Usando la intercalación “fr_FR”:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "fr_FR";

results:
==============
bernard
boris
béatrice
bérénice

Usando la intercalación “en_US”:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "en_US";

results:
==============
bernard
boris
béatrice
bérénice

En mi sistema, la configuración de intercalación (a nivel del sistema operativo) es la misma para “fr_FR” y “en_US”, como se demuestra en el shell al ejecutar diff:

cd /usr/share/locale
diff fr_FR.UTF-8/LC_COLLATE en_US.UTF-8/LC_COLLATE

Esperemos que esta información adicional sea útil para cualquiera que lea esto y esté usando PostgreSQL en una Mac que sufra este problema.

Comentarios y calificaciones del tutorial

Más adelante puedes encontrar las acotaciones de otros administradores, tú aún eres capaz insertar el tuyo si te apetece.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *