2015-08-27 207 views
0

我一直在從MySQL導入一些數據到Postgres,計劃應該很簡單 - 手動重新創建具有等效數據類型的表,將輸出方式作爲CSV,傳輸數據,將其複製到Postgres中。完成。用於編碼「UTF8」的無效字節序列:0xed 0xa0 0xbd

mysql -u whatever -p whatever -d the_database 

SELECT * INTO OUTFILE '/tmp/the_table.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\' FROM the_table; 

發送和進口的Postgres

psql -etcetc -d other_database 

COPY the_table FROM '/csv/file/location/the_table.csv' WITH(FORMAT CSV, DELIMITER ',', QUOTE '"', ESCAPE '\', NULL '\N'); 

它已經太久了,我已經忘記了,「0000-00-00」是一件事...... 所以首先我不得不拿出解決怪異的數據類型的一些方法,最好是在MySQL的結束,所以寫了這個劇本,20頁左右的表我計劃導入,以解決任何imcompatabilities並列出了相應的列

with a as (
    select 
     'the_table'::text as tblname, 
     'public'::text as schname 
), b as (
    select array_to_string(array_agg(x.column_name), ',') as the_cols from (
     select 
      case 
       when udt_name = 'timestamp' 
       then 'NULLIF('|| column_name::text || ',''0000-00-00 00:00:00'')' 
       when udt_name = 'date' 
       then 'NULLIF('|| column_name::text || ',''0000-00-00'')' 
       else column_name::text 
      end as column_name 
     from information_schema.columns, a 
     where table_schema = a.schname 
     and table_name = a.tblname 
     order by ordinal_position 
    ) x 
) 
select 'SELECT '|| b.the_cols ||' INTO OUTFILE ''/tmp/'|| a.tblname ||'.csv'' FIELDS TERMINATED BY '','' OPTIONALLY ENCLOSED BY ''"'' ESCAPED BY ''\\'' FROM '|| a.tblname ||';' from a,b; 

生成CSV,確定。跨越傳輸,確定 - 一旦結束了...

BEGIN; 
ALTER TABLE the_table SET(autovacuum_enabled = false, toast.autovacuum_enabled = false); 
COPY the_table FROM '/csv/file/location/the_table.csv' WITH(FORMAT CSV, DELIMITER ',', QUOTE '"', ESCAPE '\', NULL '\N'); -- ' 
ALTER TABLE the_table SET(autovacuum_enabled = true, toast.autovacuum_enabled = true); 
COMMIT; 

和它一切正常,直到我碰到這個消息傳來:

ERROR: invalid byte sequence for encoding "UTF8": 0xed 0xa0 0xbd 
CONTEXT: COPY new_table, line 12345678 

第二臺也遇到了同樣的錯誤,但每隔一個成功導入。 現在在MySQL數據庫中的所有列和表分別設置爲utf8,包含的信息第一得罪桌子沿

CREATE TABLE whatever(
col1 int(11) NOT NULL AUTO_INCREMENT, 
col2 date, 
col3 int(11), 
col4 int(11), 
col5 int(11), 
col6 int(11), 
col7 varchar(64), 
PRIMARY KEY(col1) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

的線,所以想必該數據應該是UTF ...對不對?確保有我編輯my.cnf中,以確保一切我能想到的,包括編碼

[character sets] 
default-character-set=utf8 
default-character-set=utf8 
character-set-server = utf8 
collation-server = utf8_unicode_ci 
init-connect='SET NAMES utf8' 

我改變了我最初的「查詢生成查詢」 case語句轉換成列的緣故沒有大的錯誤轉換

 case 
      when udt_name = 'timestamp' 
      then 'NULLIF('|| column_name::text || ',''0000-00-00 00:00:00'')' 
      when udt_name = 'date' 
      then 'NULLIF('|| column_name::text || ',''0000-00-00'')' 
      when udt_name = 'text' 
      then 'CONVERT('|| column_name::text || ' USING utf8)' 
      else column_name::text 
     end as column_name 

仍然沒有運氣。谷歌搜索「0xed 0xa0 0xbd」之後,我仍然不明智,字符集並不是我的東西。 我甚至打開3 gig csv文件到它提到的那一行,看起來沒有什麼不合適的地方,用十六進制編輯器看,我看不到那些字節值(編輯:也許我沒有看夠硬)所以我開始用盡想法。我是否錯過了一些非常簡單的事情,而且令人擔憂的是,其他一些表格可能是否已被更「默默」地破壞?

MySQL的版本是44年5月5日Ubuntu的14.04操作系統和Postgres的是9.4

+0

從[這個答案中的表格](http://stackoverflow.com/a/6555104/1411457)看,0xed 0xa0 0xbd肯定是無效的UTF8。但是如果文件不包含那個字節序列,我看不出如何得到這個錯誤。 – harmic

+0

該序列編碼代碼點'U + d83d'。這是一個結構上有效的序列,但它編碼了一個無效的字符。 http://www.charbase.com/d83d-unicode-invalid-character。猜測,MySQL的驗證比PostgreSQL更爲鬆散,所以MySQL允許它和PostgreSQL拒絕它。 –

+0

搜索「unicode eda0bd」 - 它似乎有效,但未指定:http://dev.networkerror.org/utf8/?start=55335&end=55590&cols=4&show_uni_int=on&show_uni_hex=on&show_html_ent=on&show_raw_hex=on&show_raw_bin=on –

回答

0

沒有任何進一步的東西去嘗試我去最簡單的解決方案,只需更改文件

iconv -f utf-8 -t utf-8 -c the_file.csv > the_file_iconv.csv 

新文件和原始文件之間大約有100個字節,所以在那裏肯定有無效的字節,我看不到它們,它們導入的「正確」,所以我認爲這很好,但是如果知道是否會很好在創建文件之前,有一些方法可以在導入時發現文件之前執行正確的編碼。

相關問題