Ограничението за дължина, наложено от varchar(N)
типове и се изчислява по length
функцията е в знаци, а не в байтове. Така че 'abcdef'::char(3)
се съкращава до 'abc'
но 'a€cdef'::char(3)
се съкращава до 'a€c'
, дори в контекста на база данни, кодирана като UTF-8, където 'a€c'
се кодира с помощта на 5 байта.
Ако възстановяването на дъмп файл се оплака, че 'Mér'
няма да влезе в varchar(3)
колона, което предполага, че сте възстановявали UTF-8 кодиран дъмп файл в SQL_ASCII база данни.
Например, направих това в UTF-8 база данни:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
И след това изхвърли това и се опита да го зареди в база данни SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
И със сигурност:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
Обратно, ако създам базата данни enctest като кодираща LATIN1 или UTF8, тя се зарежда добре.
Този проблем възниква поради комбинация от изхвърляне на база данни с многобайтово кодиране на знаци и опит да се възстанови в база данни SQL_ASCII. Използването на SQL_ASCII основно деактивира транскодирането на клиентски данни към сървърни данни и приема един байт на символ, оставяйки на клиентите да поемат отговорност за използването на правилната символна карта. Тъй като дъмп файлът съдържа съхранения низ като UTF-8, което е четири байта, така че базата данни SQL_ASCII вижда това като четири знака и следователно го счита за нарушаване на ограничението. И отпечатва стойността, която моят терминал след това събира отново като три знака.