2015-08-27 2 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 
      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 

и все еще не повезло. После googling «0xed 0xa0 0xbd» я все еще не мудрее, наборы символов на самом деле не мои. Я даже открыл файл csv 3 gig на упомянутой выше строке, и, похоже, не было ничего лишнего, глядя с шестнадцатеричным редактором. Я не мог видеть эти байтовые значения (редактирование: возможно, я не выглядел достаточно сложно), поэтому у меня заканчиваются идеи. Я пропустил что-то действительно простое и тревожное, возможно ли, что некоторые из других таблиц, возможно, были более «бесшумно» повреждены?

версия MySQL является 5.5.44 на 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 байт, поэтому там должно быть недопустимое количество байтов, которые я не мог видеть, они импортировали «правильно», поэтому я полагаю, что это хорошо, однако было бы неплохо узнать, если существует некоторый способ обеспечить правильное кодирование при создании файлов, прежде чем обнаруживать об этом при импорте.

 Смежные вопросы

  • Нет связанных вопросов^_^