由varchar(N)
類型施加的長度限制和由length
函數計算的長度限制是以字符而不是字節計算的。因此,'abcdef'::char(3)
被截斷爲'abc'
,但即使在編碼爲UTF-8的數據庫的上下文中,'a€cdef'::char(3)
也被截斷爲'a€c'
,其中'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數據庫將其視爲四個字符,因此將其視爲違反約束。它打印出我的終端重新組裝爲三個字符的值。
字符編碼是每個數據庫的東西。 PostgreSQL支持各種編碼,但對於給定的數據庫只能有一種編碼有效。也許你的源數據庫被設置爲與目標不同的編碼。 – Pointy 2010-11-22 20:14:44