Limit délky stanovený pomocí varchar(N)
typů a počítá se podle length
funkce je ve znacích, ne v bajtech. Takže 'abcdef'::char(3)
je zkrácen na 'abc'
ale 'a€cdef'::char(3)
je zkrácen na 'a€c'
, a to i v kontextu databáze kódované jako UTF-8, kde 'a€c'
je zakódováno pomocí 5 bajtů.
Pokud se při obnově souboru výpisu objevila stížnost, že 'Mér'
nepřejde do varchar(3)
sloupec, což naznačuje, že jste obnovovali soubor výpisu s kódováním UTF-8 do databáze SQL_ASCII.
Například jsem to udělal v databázi UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
A pak to vyhodil a pokusil se to načíst do databáze SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
A jistě:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
Naproti tomu, pokud vytvořím databázi enctest jako kódování LATIN1 nebo UTF8, načte se dobře.
K tomuto problému dochází v důsledku kombinace dumpingu databáze s vícebajtovým kódováním znaků a pokusu o její obnovení do databáze SQL_ASCII. Použití SQL_ASCII v podstatě zakáže překódování klientských dat na data serveru a předpokládá jeden bajt na znak, přičemž odpovědnost za použití správné mapy znaků ponechává na klientech. Protože soubor výpisu obsahuje uložený řetězec jako UTF-8, tedy čtyři bajty, databáze SQL_ASCII to vidí jako čtyři znaky, a proto to považuje za porušení omezení. A vypíše hodnotu, kterou pak můj terminál znovu sestaví jako tři znaky.