Aby napisać kod do sprawdzania spójności danych przechowywanych zarówno w serwerze SQL, jak iw PostgreSQL, planuję obliczyć MD5 na danych tabeli dla obu baz danych i sprawdzić, czy są one równy. Działa to dobrze, tak długo, jak dane jest zwykły tekst (ANSI), jak poniżej:Niezgodność wartości MD5 między serwerem SQL a PostgreSQL
sql-server> SELECT master.dbo.fn_varbintohexstr(HashBytes('MD5', 'a'));
0x0cc175b9c0f1b6a831c399e269772661
postgres=# select MD5('a');
0cc175b9c0f1b6a831c399e269772661
Teraz, gdy próbuję użyć niektórych Hangul (koreański) znaków, nie mecz MD5:
sql-server> SELECT master.dbo.fn_varbintohexstr(HashBytes('MD5', '무'));
0x7827b52f65d9f7777d37071cbbbf7f2d
postgres=# select MD5('무');
cb3e9be1a3a28b355eabae1fa1e291b3
Jak według mojego rozumowania, powodem niedopasowania jest to, że znaki Unicode są przechowywane jako kodowanie UCS-2 (poprawione 16-bitowe kodowanie) w serwerze SQL i kodowanie UTF-8 w PostgreSQL. A ponieważ MD5 działa na bitach znaków, sekwencja bitów znaków byłaby inna zarówno w serwerze SQL, jak iw PostgreSQL.
jak mam do czynienia głównie z Hangul zestawu znaków, obejście użyłem w PostgreSQL jest konwersja kodowania z UTF-8 do UHC (Universal hangyl zestawu znaków) przed obliczeniem hash jak poniżej:
postgres=# select MD5(CONVERT('무'::bytea,'UTF8','UHC'));
7827b52f65d9f7777d37071cbbbf7f2d
Jak widać powyższa wartość skrótu jest taka sama jak dla serwera SQL.
Wszystko jest w porządku, o ile mam do czynienia ze znakami Hangul. Ale niektóre tabele zawiera mieszankę Hangul i chińskich znaków i konwersja nie powiedzie się w tym przypadku:
postgres=# select MD5(CONVERT('무么'::bytea,'UTF8','UHC'));
ERROR: character 0xe4b988 of encoding "UTF8" has no equivalent in "UHC"
postgres=#
Błąd sens jak nie istnieją równoważne z chińskich znaków w UHC zestawu znaków.
Jak mogę to sprawić? Zasadniczo, muszę znaleźć sposób na konwersję UCS-2 na UTF-8 na serwerze SQL lub na konwersję UTF-8 na UCS-2 w PostgreSQL przed obliczeniem MD5. Chcę wykonywać wszystkie te operacje w silniku bazy danych, a nie ładować danych w zewnętrznej aplikacji do obliczania MD5, ponieważ niektóre tabele mają ogromny zestaw danych.
wersja serwera SQL 2005 PostgreSQL wersja 9.1
nie jestem pewien, że faktycznie korzysta UCS-2 (lub UTF-16) po stronie serwera SQL. '무' w utf-8 (hex) to 'EB AC B4', w utf-16be (i ucs-2be) to' BB 34', aw UHC to 'B9 AB'. Tylko ostatni daje ci hash, wspomniałeś (i oczekujesz) w swoich przykładach. – pozs
@pozs, To interesująca obserwacja. Wyglądam jak w sql-server: N '무' zapewni –
@pozs, To interesująca obserwacja. Wygląda jak w sql-server 'select N '무'' zapewni kodowanie ucs-2 przy użyciu typu nvarchar. 'select '무'' domyślnie varchar, a sekwencja bitów znaków jest określana przez sortowanie bazy danych. W moim przypadku sortowanie bazy danych sql-server jest _Korean_Wansung_CI_AS_. Wygląda na to, że sekwencja bitów znaków dla tego sortowania jest podobna do UHC. Ale w takim przypadku, jeśli chińskie znaki są obsługiwane poprawnie przez to sortowanie, dlaczego nie jest obsługiwane przez kodowanie UHC w PostgreSQL? Albo jakiego kodowania powinienem użyć w postgresie, aby obsłużyć chińskie znaki? –