PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

O varchar do Postgresql conta usando comprimento de caractere unicode ou comprimento de caractere ASCII?


O limite de comprimento imposto por varchar(N) tipos e calculados pelo length a função está em caracteres, não em bytes. Então 'abcdef'::char(3) está truncado para 'abc' mas 'a€cdef'::char(3) é truncado para 'a€c' , mesmo no contexto de um banco de dados codificado como UTF-8, onde 'a€c' é codificado usando 5 bytes.

Se restaurar um arquivo de despejo reclamou que 'Mér' não entraria em um varchar(3) coluna, que sugere que você estava restaurando um arquivo de despejo codificado em UTF-8 em um banco de dados SQL_ASCII.

Por exemplo, eu fiz isso em um banco de dados UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');

E então despejei isso e tentei carregá-lo em um banco de dados SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest

E com certeza:
psql:dump.sql:34: ERROR:  value too long for type character varying(3)
CONTEXT:  COPY t, line 1, column key: "Mér"

Por outro lado, se eu criar o banco de dados enctest como codificação LATIN1 ou UTF8, ele carrega bem.

Esse problema ocorre devido a uma combinação de despejar um banco de dados com uma codificação de caracteres de vários bytes e tentar restaurá-lo em um banco de dados SQL_ASCII. Usar SQL_ASCII basicamente desabilita a transcodificação de dados do cliente para dados do servidor e assume um byte por caractere, deixando para os clientes a responsabilidade de usar o mapa de caracteres correto. Como o arquivo de despejo contém a string armazenada como UTF-8, ou seja, quatro bytes, um banco de dados SQL_ASCII vê isso como quatro caracteres e, portanto, considera que viola a restrição. E imprime o valor, que meu terminal remonta como três caracteres.