Batas panjang yang dikenakan oleh varchar(N)
jenis dan dihitung dengan length
fungsi dalam karakter, bukan byte. Jadi 'abcdef'::char(3)
dipotong menjadi 'abc'
tapi 'a€cdef'::char(3)
dipotong menjadi 'a€c'
, bahkan dalam konteks database yang dikodekan sebagai UTF-8, di mana 'a€c'
dikodekan menggunakan 5 byte.
Jika memulihkan file dump mengeluh bahwa 'Mér'
tidak akan masuk ke varchar(3)
kolom, yang menunjukkan bahwa Anda memulihkan file dump yang disandikan UTF-8 ke database SQL_ASCII.
Misalnya, saya melakukan ini di database UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
Dan kemudian membuang ini dan mencoba memuatnya ke dalam database SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
Dan tentu saja:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
Sebaliknya, jika saya membuat database enctest sebagai pengkodean LATIN1 atau UTF8, itu memuat dengan baik.
Masalah ini muncul karena kombinasi dumping database dengan pengkodean karakter multi-byte, dan mencoba untuk mengembalikannya ke database SQL_ASCII. Menggunakan SQL_ASCII pada dasarnya menonaktifkan transcoding data klien ke data server dan mengasumsikan satu byte per karakter, menyerahkannya kepada klien untuk bertanggung jawab menggunakan peta karakter yang tepat. Karena file dump berisi string yang disimpan sebagai UTF-8, yaitu empat byte, jadi database SQL_ASCII melihatnya sebagai empat karakter, dan karena itu menganggapnya melanggar batasan. Dan itu mencetak nilainya, yang kemudian dipasang kembali oleh terminal saya sebagai tiga karakter.