Mientras importaba una base de datos Postgres desde un dump SQL en un nuevo servidor me topé con este inconveniente:

ERROR:  encoding UTF8 does not match locale es_ES.iso88591
DETAIL:  The chosen LC_CTYPE setting requires encoding LATIN1.

La codificación el template no coincide con el locale "es_ES.iso88591" y se requiere utilizar "LATIN1".



Las instrucciones SQL dentro del dump que causan este inconveniente son las siguientes:


SET client_encoding = 'LATIN1';

CREATE DATABASE pepe WITH TEMPLATE = template0 OWNER = postgres LC_COLLATE = 'es_ES.iso88591' LC_CTYPE = 'es_ES.iso88591';

Se observa que se trata de crear la base de datos "pepe" utilizando el conjunto de caracteres "es_ES.iso88591". Sin embargo, la codificación utilizada por el sistema operativo es UTF-8:

postgres@debian:~$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Al mismo tiempo, la codificación del "template0" (plantilla utilizada para la creación de la base de datos en el servidor PostgreSQL) también es UTF-8:

postgres@debian:~$ psql -c "\l"
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | es_AR.UTF-8 | es_AR.UTF-8 | 
 template0 | postgres | UTF8     | es_AR.UTF-8 | es_AR.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | es_AR.UTF-8 | es_AR.UTF-8 | postgres=CTc/postgres+
           |          |          |             |             | =c/postgres
(3 rows)

Aquí hay dos problemas: tanto el locale del sistema operativo, como la codificación del template no coinciden con el conjunto de caracteres con el que se pretende crear la nueva base de datos.

A fin de evitar errores en la codificación (que afectan principalmente a la visualización y presentación de los datos) es recomendable mantener la consistencia entre las codificaciones (conjuntos de caracteres) usadas por el sistema operativo, plantillas y bases de datos.

El sistema operativo (en este caso Debian) tiene disponibles los siguientes locales:

postgres@debian:~$ locale -a
C
C.UTF-8
en_US.utf8
es_AR
es_AR.iso88591
es_AR.utf8
es_ES
es_ES.iso88591
es_ES.utf8
POSIX
spanish

Si el locale necesario no está listado, es posible generarlo utilizando locale-gen.

Editar el archivo de configuración /etc/default/locale para cambiar el locale a nivel sistema operativo:

postgres@debian:~$ nano /etc/default/locale

Establecer el locale deseado y guardar los cambios:

#  File generated by update-locale
#LANG="en_US.UTF-8"
LANG="es_ES.iso88591"
LANGUAGE=
LC_CTYPE="es_ES.iso88591"
LC_NUMERIC="es_ES.iso88591"
LC_TIME="es_ES.iso88591"
LC_COLLATE="es_ES.iso88591"
LC_MONETARY="es_ES.iso88591"
LC_MESSAGES="es_ES.iso88591"
LC_PAPER="es_ES.iso88591"
LC_NAME="es_ES.iso88591"
LC_ADDRESS="es_ES.iso88591"
LC_TELEPHONE="es_ES.iso88591"
LC_MEASUREMENT="es_ES.iso88591"
LC_IDENTIFICATION="es_ES.iso88591"
LC_ALL=

Al iniciar sesión nuevamente, se observa el nuevo locale. Tener en cuenta que esto puede afectar la correcta visualización en nombres de directorios, archivos y su contenido.

root@debian:~# locale
LANG=es_ES.iso88591
LANGUAGE=
LC_CTYPE=es_ES.iso88591
LC_NUMERIC=es_ES.iso88591
LC_TIME=es_ES.iso88591
LC_COLLATE=es_ES.iso88591
LC_MONETARY=es_ES.iso88591
LC_MESSAGES=es_ES.iso88591
LC_PAPER=es_ES.iso88591
LC_NAME=es_ES.iso88591
LC_ADDRESS=es_ES.iso88591
LC_TELEPHONE=es_ES.iso88591
LC_MEASUREMENT=es_ES.iso88591
LC_IDENTIFICATION=es_ES.iso88591
LC_ALL=

El siguiente paso consiste en cambiar la codificación y collation del template.

Es posible cambiar el encoding del template eliminándolo y creándolo nuevamente mediante sentencias SQL. Sin embargo, en el caso de una importación (donde la instancia está aún vacía) una solución simple y rápida consiste en detener el servidor PostgreSQL, eliminar la instancia (rm -fr al directorio que contiene la instancia) y crearla nuevamente corriendo initdb.

Esto se debe a que la codificación de los templates se toma por defecto de la codificación utilizada por el sistema operativo. De esta forma, tanto el conjunto de caracteres como la collation quedan consistentes a nivel sistema operativo y bases de datos:

postgres@debian:~$ psql -c "\l"
                                         List of databases
   Name    |  Owner   | Encoding |   Collation    |     Ctype      |   Access privileges   
-----------+----------+----------+----------------+----------------+-----------------------
 postgres  | postgres | LATIN1   | es_ES.iso88591 | es_ES.iso88591 | 
 template0 | postgres | LATIN1   | es_ES.iso88591 | es_ES.iso88591 | =c/postgres          +
           |          |          |                |                | postgres=CTc/postgres
 template1 | postgres | LATIN1   | es_ES.iso88591 | es_ES.iso88591 | postgres=CTc/postgres+
           |          |          |                |                | =c/postgres

(3 rows)

Luego se procede con la importación sin errores.


Tal vez pueda interesarte


Compartí este artículo