PDA

Zobacz pełną wersję : Mysql konwersja znaków z latin2 na utf8



hazael
08-03-2008, 19:16
Witam,

Mam baze danych postawioną w latin2 (polskie czcionki w ISO) i mam zamiar przejsc na UTF.

Same ustawienia w plikach joomla z iso na utf to najmniejszy problem:

.htaccess:

AddDefaultCharset UTF-8w szablonie glowny plik index.php

<?php header('Content-type: text/html; charset=UTF-8');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"; ?>konwersja wszystkich plików z polskimi znakami w ISO

najlepiej polskim programem GżegżółkaAby system plików joomla odczytywał polskie znaki zapisane wczesniej w latin2 i przekonwertował je na UTF wystarczy w pliku
include/database.php w okolicach 100 linii znaleźć
odkomentowujesz (usuwasz znak "#" lub "//") przy linii:

@mysql_query("SET NAMES 'latin2'", $this->_resource); - zmieniamy latin2 na utf8 i teoretycznie problem z głowy.

Jednak to rozwiazanie nie do konca mnie zadowala. Generalnie chce, aby cała baza byla przekonwertowana na utf8. W bazie zmieniłem juz sposób porownywania znaków ale to nic nie daje. W zasadzie w bazie danych mozna zmieniac wybiorczo znaki lub całe wyrazenia metodą:


UPDATE jos_tabela SET `nazwa_kolumny` = REPLACE(`nazwa_kolumny`, 'stara nazwa',
'nowa nazwa') WHERE `nazwa_kolumny` LIKE '%stara nazwa%';
ale jak mam zmieniac tak cała baze danych to... :D

Wtakim razie jak mozna szybko i bezbolesnie przekonwertowac całą baze mającą ok 50MB?
Prosze napisać dokładnie krok po kroku taką czynność o ile jest to mozliwe, a wiem ze jest.

hazael
10-03-2008, 18:52
Troche poczytałem sobie i rozwiazanie okazało się banalnie proste:)

robimy zrzut bazy danych na serwer i z konta np shell'owego sprawdzamy czy system obsługuje iconv - wydajemy polecenie np:

iconv --helpsamo konwertowanie trwa bardoz krótko - wystarczy wpisac polecenie:

iconv -f kodowanie -t kodowanie-docelowe plik > plik-wynikowyna przyklad jezeli chcemy przekonwertowac plik z iso-8859-2 na utf-8:

iconv -f iso-8859-2 -t utf-8 jos_content.sql > jos_content-utf8.sql:cool:

hazael
10-03-2008, 19:05
Jezeli skonczylismy konwertowanie wszystkich znaków i wrzucilismy to wszystko do bazy danych to ostatnią cyznnoscią jaką nas czeka jest szybka zmiana: Metoda porównywania napisów

Oczywiscie tabelek mamy bardzo duzo pomijając juz ich strukture, wiec robimy sobie taki skrypcik:



<?php
set_time_limit(0);
$convert_from = 'latin2_general_ci';
$convert_to = 'utf8_polish_ci';
$character_set= 'utf8';

//zmiana kodowania tabel (true/false)
$show_alter_table = true;
//zmiana kodowania struktury tabeli (true/false)
$show_alter_field = true;

// baza danych:
$username = '';
$password = '';
$database = '';
$host = 'localhost';

mysql_connect($host, $username, $password);
mysql_select_db($database);

$rs_tables = mysql_query(" SHOW TABLES ") or die(mysql_error());

print '<pre>';
while ($row_tables = mysql_fetch_row($rs_tables)) {
$table = mysql_real_escape_string($row_tables[0]);
if ($show_alter_table) {
echo("ALTER TABLE `$table` DEFAULT CHARACTER SET $character_set;\r\n");
}

$rs = mysql_query(" SHOW FULL FIELDS FROM `$table` ") or die(mysql_error());
while ($row=mysql_fetch_assoc($rs)) {

if ($row['Collation']!=$convert_from)
continue;

if ($row['Null']=='YES') {
$nullable = ' NULL ';
} else {
$nullable = ' NOT NULL';
}

// Does the field default to null, a string, or nothing?
if ($row['Default']==NULL) {
$default = " DEFAULT NULL";
} else if ($row['Default']!='') {
$default = " DEFAULT '".mysql_real_escape_string($row['Default'])."'";
} else {
$default = '';
}

CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
if ($show_alter_field) {
$field = mysql_real_escape_string($row['Field']);
echo "ALTER TABLE `$table` CONVERT TO CHARACTER SET $character_set COLLATE $convert_to; \r\n";
}
}
}

?>

Plik wrzucamy na serwer i go uruchamiamy. Wygenerują sie nam wszystkie zapytania do bazy danych, które nalezy przekopiowac i wykonać (np w phpMyAdmin)... I to byłoby na tyle :)

hazael
10-03-2008, 19:23
Może sie zdarzyć, że nasz serwer nie obsługuje iconv, lub po prostu nie mamy dostępu, aby uruchomić takie działanie.

Zawsze mozemy wybrac inną metodę konwersji znaków - niestety ma ona kilka wad - nie wszędzie to zadziała. Na przykład nalezy pominąć takie miejsca, które wskazują na tytuł, metadane, menu itp.. Konwertujemy tylko tresc!
Kolejną wadą jest sam fakt, że baza danych lekko nam się powiekszy w swojej obietosci ;)

Wystarczy lekko zmodyfikować powyższy skrypt wykonujac coś takiego:



<?php
set_time_limit(0);

//jezeli mamy tabele w innym kodowaniu niż na to wskazuje $convert_from to nalezy to wskazać

$convert_from = 'latin2_general_ci';
$convert_to = 'utf8_polish_ci';
$character_set= 'utf8';

//zmiana kodowania tabel (true/false)
$show_alter_table = false;
//zmiana kodowania struktury tabeli (true/false)
$show_alter_field = true;

// baza danych:
$username = '';
$password = '';
$database = '';
$host = 'localhost';

mysql_connect($host, $username, $password);
mysql_select_db($database);

$rs_tables = mysql_query(" SHOW TABLES ") or die(mysql_error());

print '<pre>';
while ($row_tables = mysql_fetch_row($rs_tables)) {
$table = mysql_real_escape_string($row_tables[0]);
if ($show_alter_table) {
echo("ALTER TABLE `$table` DEFAULT CHARACTER SET $character_set;\r\n");
}

$rs = mysql_query(" SHOW FULL FIELDS FROM `$table` ") or die(mysql_error());
while ($row=mysql_fetch_assoc($rs)) {

if ($row['Collation']!=$convert_from)
continue;

if ($row['Null']=='YES') {
$nullable = ' NULL ';
} else {
$nullable = ' NOT NULL';
}

// Does the field default to null, a string, or nothing?
if ($row['Default']==NULL) {
$default = " DEFAULT NULL";
} else if ($row['Default']!='') {
$default = " DEFAULT '".mysql_real_escape_string($row['Default'])."'";
} else {
$default = '';
}

CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
if ($show_alter_field) {
$field = mysql_real_escape_string($row['Field']);


echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ą','&amp;#260;') WHERE `$field` LIKE '%Ą%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ą','&amp;#261;') WHERE `$field` LIKE '%ą%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ć','&amp;#262;') WHERE `$field` LIKE '%Ć%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ć','&amp;#263;') WHERE `$field` LIKE '%ć%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ć','&amp;#263;') WHERE `$field` LIKE '%ć%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ę','&amp;#281;') WHERE `$field` LIKE '%ę%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ł','&amp;#321;') WHERE `$field` LIKE '%Ł%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ł','&amp;#322;') WHERE `$field` LIKE '%ł%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ń','&amp;#323;') WHERE `$field` LIKE '%Ń%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ń','&amp;#324;') WHERE `$field` LIKE '%ń%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ó','&amp;#211;') WHERE `$field` LIKE '%Ó%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ó','&amp;#243;') WHERE `$field` LIKE '%ó%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ś','&amp;#346;') WHERE `$field` LIKE '%Ś%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ś','&amp;#347;') WHERE `$field` LIKE '%ś%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ź','&amp;#377;') WHERE `$field` LIKE '%Ź%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ź','&amp;#378;') WHERE `$field` LIKE '%ź%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'Ż','&amp;#379;') WHERE `$field` LIKE '%Ż%'; \r\n";
echo "UPDATE `$table` SET `$field` = REPLACE(`$field`, 'ż','&amp;#380;') WHERE `$field` LIKE '%ż%'; \r\n";



}
}
}

?>