Spędziłem ostatnie 8 godzin, próbując zaimportować dane wyjściowe „mysqldump --compatible = postgresql” do PostgreSQL 8.4.9, i przeczytałem już co najmniej 20 różnych wątków tutaj i gdzie indziej na temat tego konkretnego problemu, ale nie znalazłem prawdziwa użyteczna odpowiedź, która działa.
Zrzucone dane MySQL 5.1.52:
mysqldump -u root -p --compatible=postgresql --no-create-info --no-create-db --default-character-set=utf8 --skip-lock-tables rt3 > foo
Serwer PostgreSQL 8.4.9 jako miejsce docelowe
Ładowanie danych za pomocą polecenia „psql -U rt_user -f foo” zgłasza się (wiele z nich, oto jeden przykład):
psql:foo:29: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".
Zgodnie z tym, w pliku wejściowym nie ma znaków NULL (0x00).
database-dumps:rcf-temp1# sed 's/\x0/ /g' < foo > nonulls
database-dumps:rcf-temp1# sum foo nonulls
04730 2545610 foo
04730 2545610 nonulls
database-dumps:rcf-temp1# rm nonulls
Podobnie, kolejne sprawdzenie za pomocą Perla pokazuje brak wartości NULL:
database-dumps:rcf-temp1# perl -ne '/\000/ and print;' foo
database-dumps:rcf-temp1#
Jak wspomina „WSKAZÓWKA” w błędzie, próbowałem wszystkich możliwych sposobów, aby ustawić „kod_klienta” na „UTF8”, ale mi się to udaje, ale nie ma to wpływu na rozwiązanie mojego problemu.
database-dumps:rcf-temp1# psql -U rt_user --variable=client_encoding=utf-8 -c "SHOW client_encoding;" rt3
client_encoding
-----------------
UTF8
(1 row)
database-dumps:rcf-temp1#
Idealne, ale:
database-dumps:rcf-temp1# psql -U rt_user -f foo --variable=client_encoding=utf-8 rt3
...
psql:foo:29: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".
...
Z wyjątkiem poprawnej odpowiedzi „Według Hoyle'a”, która byłaby fantastyczna do usłyszenia i wiedząc, że tak naprawdę nie dbam o zachowanie znaków spoza ASCII dla tych rzadko odwoływanych danych, jakie masz sugestie?
Aktualizacja: Podczas importu pojawia się ten sam błąd w wersji tego samego pliku zrzutu tylko do ASCII. Naprawdę zadziwiające:
database-dumps:rcf-temp1# # convert any non-ASCII character to a space
database-dumps:rcf-temp1# perl -i.bk -pe 's/[^[:ascii:]]/ /g;' mysql5-dump.sql
database-dumps:rcf-temp1# sum mysql5-dump.sql mysql5-dump.sql.bk
41053 2545611 mysql5-dump.sql
50145 2545611 mysql5-dump.sql.bk
database-dumps:rcf-temp1# cmp mysql5-dump.sql mysql5-dump.sql.bk
mysql5-dump.sql mysql5-dump.sql.bk differ: byte 1304850, line 30
database-dumps:rcf-temp1# # GOOD!
database-dumps:rcf-temp1# psql -U postgres -f mysql5-dump.sql --variable=client_encoding=utf-8 rt3
...
INSERT 0 416
psql:mysql5-dump.sql:30: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encod.
INSERT 0 455
INSERT 0 424
INSERT 0 483
INSERT 0 447
INSERT 0 503
psql:mysql5-dump.sql:36: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encod.
INSERT 0 502
INSERT 0 507
INSERT 0 318
INSERT 0 284
psql:mysql5-dump.sql:41: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encod.
INSERT 0 382
INSERT 0 419
INSERT 0 247
psql:mysql5-dump.sql:45: ERROR: invalid byte sequence for encoding "UTF8": 0x00
HINT: This error can also happen if the byte sequence does not match the encod.
INSERT 0 267
INSERT 0 348
^C
Jedna z omawianych tabel jest zdefiniowana jako:
Table "public.attachments"
Column | Type | Modifie
-----------------+-----------------------------+--------------------------------
id | integer | not null default nextval('atta)
transactionid | integer | not null
parent | integer | not null default 0
messageid | character varying(160) |
subject | character varying(255) |
filename | character varying(255) |
contenttype | character varying(80) |
contentencoding | character varying(80) |
content | text |
headers | text |
creator | integer | not null default 0
created | timestamp without time zone |
Indexes:
"attachments_pkey" PRIMARY KEY, btree (id)
"attachments1" btree (parent)
"attachments2" btree (transactionid)
"attachments3" btree (parent, transactionid)
Nie mam możliwości zmiany typu żadnej części schematu DB. Takie postępowanie prawdopodobnie zepsułoby przyszłe aktualizacje oprogramowania itp.
Prawdopodobną kolumną problemu jest „treść” typu „tekst” (być może także inne w innych tabelach). Jak już wiem z poprzednich badań, PostgreSQL nie zezwoli na NULL w wartościach „tekstowych”. Jednak zobacz wyżej, gdzie zarówno sed, jak i Perl nie wyświetlają znaków NULL, a następnie dalej w dół, gdzie usuwam wszystkie znaki spoza ASCII z całego pliku zrzutu, ale nadal pojawia się błąd.
head -29 foo | tail -1 | cat -v
.