Giới hạn độ dài do varchar(N)
áp đặt loại và được tính bằng length
hàm là ký tự, không phải byte. Vì vậy, 'abcdef'::char(3)
được cắt ngắn thành 'abc'
nhưng 'a€cdef'::char(3)
được cắt ngắn thành 'a€c'
, ngay cả trong ngữ cảnh của cơ sở dữ liệu được mã hóa là UTF-8, trong đó 'a€c'
được mã hóa bằng 5 byte.
Nếu khôi phục tệp kết xuất khiếu nại rằng 'Mér'
sẽ không đi vào varchar(3)
, điều đó cho thấy bạn đang khôi phục tệp kết xuất được mã hóa UTF-8 vào cơ sở dữ liệu SQL_ASCII.
Ví dụ:tôi đã thực hiện việc này trong cơ sở dữ liệu UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
Và sau đó kết xuất nó và cố gắng tải nó vào cơ sở dữ liệu SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
Và chắc chắn:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
Ngược lại, nếu tôi tạo cơ sở dữ liệu enctest dưới dạng mã hóa LATIN1 hoặc UTF8, nó sẽ tải tốt.
Sự cố này xảy ra do sự kết hợp của việc kết xuất cơ sở dữ liệu với mã hóa ký tự nhiều byte và cố gắng khôi phục nó thành cơ sở dữ liệu SQL_ASCII. Sử dụng SQL_ASCII về cơ bản vô hiệu hóa việc chuyển mã dữ liệu máy khách sang dữ liệu máy chủ và giả định một byte cho mỗi ký tự, để máy khách chịu trách nhiệm sử dụng đúng bản đồ ký tự. Vì tệp kết xuất chứa chuỗi được lưu trữ dưới dạng UTF-8, đó là bốn byte, vì vậy cơ sở dữ liệu SQL_ASCII coi đó là bốn ký tự và do đó coi nó là vi phạm ràng buộc. Và nó in ra giá trị, sau đó thiết bị đầu cuối của tôi sẽ tập hợp lại thành ba ký tự.