Limit długości nałożony przez varchar(N)
typy i obliczane przez length
funkcja jest w znakach, a nie w bajtach. Więc 'abcdef'::char(3)
jest obcięty do 'abc'
ale 'a€cdef'::char(3)
jest obcinany do 'a€c'
, nawet w kontekście bazy danych zakodowanej jako UTF-8, gdzie 'a€c'
jest zakodowany przy użyciu 5 bajtów.
Jeśli przywracanie pliku zrzutu skarżyło się, że 'Mér'
nie trafi do varchar(3)
kolumna, która sugeruje, że przywracasz plik zrzutu zakodowany w UTF-8 do bazy danych SQL_ASCII.
Na przykład zrobiłem to w bazie danych UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
A potem zrzuciłem to i próbowałem załadować do bazy danych SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
I rzeczywiście:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
W przeciwieństwie do tego, jeśli utworzę enctest bazy danych jako kodujący LATIN1 lub UTF8, ładuje się dobrze.
Ten problem pojawia się z powodu połączenia zrzucania bazy danych z wielobajtowym kodowaniem znaków i próby przywrócenia jej do bazy danych SQL_ASCII. Użycie SQL_ASCII zasadniczo wyłącza transkodowanie danych klienta na dane serwera i przyjmuje jeden bajt na znak, pozostawiając klientom odpowiedzialność za użycie właściwej mapy znaków. Ponieważ plik zrzutu zawiera zapisany ciąg znaków jako UTF-8, czyli cztery bajty, baza danych SQL_ASCII widzi to jako cztery znaki i dlatego traktuje je jako naruszenie ograniczenia. I wypisuje wartość, którą mój terminal składa w trzy znaki.