Всем привет. Столкнулся с вопросом конвертации базы из CP1251 в UTF8.
Полазив по просторам Интернета не нашел готового скрита (видимо плохо искал).
Вот решил написать свой скриптп. Конвертация происходит безо всяких дампов базы. Решены проблемы с символами е = ё и т.д.
Пользуйтесь на здоровье.
Исправьте в начале скрипта открывающий тег. Хабр его режет, пришлось заэкранировать вопросик
UPD:
По просьбам трудящихся описываю алгоритм работы:
1. Переименовываем таблицу во временную.
2. Берем описание таблицы. В ней меняем defaul charset на utf8. Ставим collate utf8_bin(делается, чтобы буквы нормлаьно перекодировались. И не было проблем с е = ё и т.д. Но есть 1 трабла — при сравнении строковых значений будет учитываться регистр).
3. Отключаем использование ключей(увеличивается скорость вставки). ALTER TABLE table_in_utf8 DISABLE KEYS;
4. Вставляем данные из таблицы, которая у нас в cp1251 в таблицу с кодировкой utf8. INSERT INTO table_in_utf8 SELECT * FROM table_in_cp1251;
5. Включаем использование ключей ALTER TABLE table_in_utf8 ENABLE KEYS;
Ну а скриптег написан для того, чтобы не делать все это ручками, если в вашем проекте очень много таблиц.
запускать скрипт можно из консоли `php -f export.php` или через веб.
$time = microtime(true);
$db = ‘vspomni’;
$login = ‘vspomni’;
$passw = »;
$host = ‘vspomni.ru’;
$res = mysql_connect($host, $login, $passw);
mysql_select_db($db);
mysql_query(‘SET NAMES utf8;’);
$rs = mysql_query(‘SHOW TABLES;’);
print mysql_error(); //the notorious ‘command out of synch’ message
while (($row=mysql_fetch_assoc($rs))!==false) {
$time1 = microtime(true);
//print $row[‘Tables_in_vspomni2’].»\n»;
$table_name = $row[‘Tables_in_’.$db];
$query = ‘SHOW CREATE TABLE ‘.$table_name;
$row_create = mysql_query($query);
print mysql_error();
$row1 = mysql_fetch_assoc($row_create);
if (strpos($row1[‘Create Table’], ‘DEFAULT CHARSET=utf8’) !== false)
{
print ‘Table ‘.$table_name.’ — skipped’.»\n»;
continue;
}
$create_table_scheme = str_ireplace(‘cp1251’, ‘utf8’, $row1[‘Create Table’]); // CREATE TABLE SCHEME
$create_table_scheme = str_ireplace(‘ENGINE=InnoDB’, ‘MyISAM’, $create_table_scheme);
$create_table_scheme .= ‘ COLLATE utf8_bin’;
//print $create_table_scheme;
//continue;
$query = ‘RENAME TABLE ‘.$table_name.’ TO ‘.$table_name.’_tmp_export’; // RENAME TABLE;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
$query = $create_table_scheme;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
$query = ‘ALTER TABLE ‘.$table_name.’ DISABLE KEYS’;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
$query = ‘INSERT INTO ‘.$table_name.’ SELECT * FROM ‘.$table_name.’_tmp_export’;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
$query = ‘DROP TABLE ‘.$table_name.’_tmp_export’;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
$time3 = microtime(true);
$query = ‘ALTER TABLE ‘.$table_name.’ ENABLE KEYS’;
mysql_query($query);
$error = mysql_error();
if (strlen($error) > 0)
{
print $error.’ — LINE ‘.__LINE__.»\n»;
break;
}
print ‘Enable keys to ‘.$table_name.’. time -‘.(microtime(true) — $time3).»\n»;
print ‘converted ‘.$table_name.’. time — ‘.(microtime(true) — $time1).»\n\n»;
}
mysql_free_result($rs);
print ‘done. total time -‘.(microtime(true) — $time);
?>
P.S. Сегодня ночью БД проекта вспомни.ру сконвертировал этим скриптом за 17 минут.
Часто случается, что необходимо выполнить конвертацию существующей базы из одной кодировки в другую. Нам чаще всего приходится конвертировать из Win-1251 в UTF-8. Это можно произвести разными способами, но самый быстрый и простой — использование SQL-запроса.
Запрос конвертирования кодировки:
ALTER TABLE `db_name`.`table_name` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
При помощи этого запроса, можно конвертировать таблицу базы данных в любую, доступную в MySQL кодировку. Но что делать, если таблиц 100, 200 или больше, и все таблицы необходимо перекодировать в UTF8 из Win-1251? Для решения этой проблемы, можно отправить в MySQL запрос, который сгенерирует необходимые SQL-запросы для всех таблиц БД.
При использовании, например, PHPMyAdmin
останется только скопировать результаты и запустить их как SQL-запрос:
SELECT CONCAT( 'ALTER TABLE `', t.`TABLE_SCHEMA` , '`.`', t.`TABLE_NAME` , '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' ) AS sqlcode
FROM `information_schema`.`TABLES` t
WHERE 1
AND t.`TABLE_SCHEMA` = 'My_DB_for_convert'
ORDER BY 1
LIMIT 0 , 90
Этот запрос будет работать в MySQL версии 5 и выше. My_DB_for_convert
— следует заменить на имя БД, таблицы в которой необходимо конвертировать в UTF-8.
utf8_general_ci или utf8_unicode_ci
utf8_general_ci
и utf8_unicode_ci
отличаются только скоростью работы и порядком сортировки. Поскольку utf8_general_ci работает быстрее — это и есть предпочтительный выбор. В случаее необходимости, способом описанным выше, можно будет изменить подкодировку UTF8 c utf8_general_ci на utf8_unicode_ci.
Попросили тут перенести сайт на другой хостинг, а он, как оказалось, до сих пор жил в кодировке cp1251. Вроде ничего страшного — работает, но уж больно по колхозному это в наше время и давно пора перейти на UTF-8.
Перед любыми действиями с базой данных ОБЯЗАТЕЛЬНО СОЗДАЕМ РЕЗЕРВНУЮ КОПИЮ!
Самый быстрый и простой способ — пересохранить копию базу данных в любом текстовом редакторе (sublime text, notepad++) в нужной кодировке и импортировать на место старой. Можно проделать данную операцию используя SQL-запросы в phpMyAdmin.
ALTER DATABASE имя_вашей_базы_данных charset=utf8;
Данный запрос конвертирует базу в указанную кодировку. Кроме этого потребуется конвертировать и сами таблицы. Запрос для конвертации таблицы базы данных:
ALTER TABLE `db_name`.`table_name` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
Конвертировать каждую из таблиц по отдельности подобным образом то ещё удовольствие, особенно при большом количестве. Однако можно не мучить себя подобным занятием, а создать последовательность команд посредством одного запроса:
SELECT CONCAT( 'ALTER TABLE `', t.`TABLE_SCHEMA` , '`.`', t.`TABLE_NAME` , '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' ) AS sqlcode FROM `information_schema`.`TABLES` t WHERE 1 AND t.`TABLE_SCHEMA` = 'My_DB_for_convert' ORDER BY 1 LIMIT 0 , 90
Остается только скопировать результаты и вставить их в форму нового SQL запроса.
Подписывайтесь на канал
Яндекс.Дзен
и узнавайте первыми о новых материалах, опубликованных на сайте.
Некоторые неудобства с кодировкой windows-1251 заставляют задуматься о том, как перевести кодировку проекта на другую, к примеру, UTF-8. С файлами — всё проще, открываем в редакторе (к примеру, Notepad++) файлы скриптов, преобразуем их кодировку UTF-8/без BOM, сохраняем. Однако если ваш сайт использует для хранения данных базу (зачастую MySQL), то вам необходимо конвертировать так же кодировку базы данных. Выполнение данной задачи предусматривает разные способы. Здесь мы рассмотрим, пожалуй, самый быстрый и простой способ. Делать мы это будем посредством использования SQL-запроса.
Запрос для конвертации базы:
ALTER TABLE `db_name`.`table_name` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
Данный запрос конвертирует базу в указанную кодировку, доступную для MySQL. Кроме этого потребуется конвертировать кодировку самих таблиц. Можно производить конвертацию таблиц по отдельности каждую, неудобство возникает при большом количестве таблиц. К счастью, мучить себя этим рутинным занятием не придется, т.к. можно это сделать посредством одного запроса.
Запрос для конвертации таблиц базы данных:
SELECT CONCAT( 'ALTER TABLE `', t.`TABLE_SCHEMA` , '`.`', t.`TABLE_NAME` , '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' ) AS sqlcode FROM `information_schema`.`TABLES` t WHERE 1 AND t.`TABLE_SCHEMA` = 'My_DB_for_convert' ORDER BY 1 LIMIT 0 , 90
Вместо My_DB_for_convert вам необходимо указать имя своей базы данных. Данный запрос будет работать в MySQL начиная с версии 5 и выше. В случае с использованием утилиты phpMyAdmin всё проще простого, остается только скопировать данный запрос и вставить в форму SQL запроса.
Стоит обратить внимание на то, что существуют подкодировки UTF-8, популярные из них:
utf8_general_ci и utf8_unicode_ci
Скорость работы, и порядок сортировки у этих родственных кодировок разная, собственно это их и отличает друг от друга. utf8_general_ci – работает немного быстрее, поэтому предпочтение отдается именно этой кодировке. Разница разумеется мизерна, для того чтобы заметить это в действительности на производительности базы, однако такие сведения есть.
Function | Return Type | Description | Example | Result |
---|---|---|---|---|
|
int |
ASCII code of the first character of the argument. For UTF8 returns the Unicode code point of the character. For other multibyte encodings, the argument must be an ASCII character. |
ascii('x') |
120 |
|
text |
Remove the longest string consisting only of characters in characters (a space by default)from the start and end of string
|
btrim('xyxtrimyyx', 'xyz') |
trim |
|
text |
Character with the given code. For UTF8 the argument is treated as a Unicode code point. For other multibyte encodings the argument must designate an ASCII character. The NULL (0) character is not allowed because text data types cannot store such bytes. |
chr(65) |
A |
|
text |
Concatenate the text representations of all the arguments. NULL arguments are ignored. |
concat('abcde', 2, NULL, 22) |
abcde222 |
|
text |
Concatenate all but the first argument with separators. The first argument is used as the separator string. NULL arguments are ignored. |
concat_ws(',', 'abcde', 2, NULL, 22) |
abcde,2,22 |
|
bytea |
Convert string to dest_encoding . Theoriginal encoding is specified by src_encoding . Thestring must be valid in this encoding.Conversions can be defined by CREATE CONVERSION .Also there are some predefined conversions. See Table 9.10 for available conversions. |
convert('text_in_utf8', 'UTF8', 'LATIN1') |
text_in_utf8 represented in Latin-1encoding (ISO 8859-1) |
|
text |
Convert string to the database encoding. The original encoding is specified by src_encoding . Thestring must be valid in this encoding.
|
convert_from('text_in_utf8', 'UTF8') |
text_in_utf8 represented in the current database encoding |
|
bytea |
Convert string to dest_encoding .
|
convert_to('some text', 'UTF8') |
some text represented in the UTF8 encoding |
|
bytea |
Decode binary data from textual representation in string .Options for format are same as in encode .
|
decode('MTIzAAE=', 'base64') |
\x3132330001 |
|
text |
Encode binary data into a textual representation. Supported formats are: base64 , hex , escape .escape converts zero bytes and high-bit-set bytes tooctal sequences ( \ nnn ) anddoubles backslashes. |
encode('123\000\001', 'base64') |
MTIzAAE= |
|
text |
Format arguments according to a format string. This function is similar to the C function sprintf .See Section 9.4.1. |
format('Hello %s, %1$s', 'World') |
Hello World, World |
|
text |
Convert the first letter of each word to upper case and the rest to lower case. Words are sequences of alphanumeric characters separated by non-alphanumeric characters. |
initcap('hi THOMAS') |
Hi Thomas |
|
text |
Return first n characters in the string. When n is negative, return all but last | n | characters.
|
left('abcde', 2) |
ab |
|
int |
Number of characters in string
|
length('jose') |
4 |
|
int |
Number of characters in string in the givenencoding . The string must be valid in this encoding. |
length('jose', 'UTF8') |
4 |
|
text |
Fill up the string to lengthlength by prepending the charactersfill (a space by default). If thestring is already longer thanlength then it is truncated (on theright). |
lpad('hi', 5, 'xy') |
xyxhi |
|
text |
Remove the longest string containing only characters fromcharacters (a space by default) from the start ofstring
|
ltrim('zzzytest', 'xyz') |
test |
|
text |
Calculates the MD5 hash of string ,returning the result in hexadecimal |
md5('abc') |
900150983cd24fb0 d6963f7d28e17f72 |
|
text[] |
Split qualified_identifier into an array ofidentifiers, removing any quoting of individual identifiers. By default, extra characters after the last identifier are considered an error; but if the second parameter is false , then suchextra characters are ignored. (This behavior is useful for parsing names for objects like functions.) Note that this function does not truncate over-length identifiers. If you want truncation you can cast the result to name[] .
|
parse_ident('"SomeSchema".someTable') |
{SomeSchema,sometable} |
|
name |
Current client encoding name | pg_client_encoding() |
SQL_ASCII |
|
text |
Return the given string suitably quoted to be used as an identifier in an SQL statement string. Quotes are added only if necessary (i.e., if the string contains non-identifier characters or would be case-folded). Embedded quotes are properly doubled. See also Example 43.1. |
quote_ident('Foo bar') |
"Foo bar" |
|
text |
Return the given string suitably quoted to be used as a string literal in an SQL statement string. Embedded single-quotes and backslashes are properly doubled. Note that quote_literal returns null on nullinput; if the argument might be null, quote_nullable is often more suitable.See also Example 43.1. |
quote_literal(E'O\'Reilly') |
'O''Reilly' |
|
text |
Coerce the given value to text and then quote it as a literal. Embedded single-quotes and backslashes are properly doubled. |
quote_literal(42.5) |
'42.5' |
|
text |
Return the given string suitably quoted to be used as a string literal in an SQL statement string; or, if the argument is null, return NULL .Embedded single-quotes and backslashes are properly doubled. See also Example 43.1. |
quote_nullable(NULL) |
NULL |
|
text |
Coerce the given value to text and then quote it as a literal; or, if the argument is null, return NULL .Embedded single-quotes and backslashes are properly doubled. |
quote_nullable(42.5) |
'42.5' |
|
text[] |
Return captured substring(s) resulting from the first match of a POSIX regular expression to the string . SeeSection 9.7.3 for more information. |
regexp_match('foobarbequebaz', '(bar)(beque)') |
{bar,beque} |
|
setof text[] |
Return captured substring(s) resulting from matching a POSIX regular expression to the string . SeeSection 9.7.3 for more information. |
regexp_matches('foobarbequebaz', 'ba.', 'g') |
{bar}
(2 rows) |
|
text |
Replace substring(s) matching a POSIX regular expression. See Section 9.7.3 for more information. |
regexp_replace('Thomas', '.[mN]a.', 'M') |
ThM |
|
text[] |
Split string using a POSIX regular expression asthe delimiter. See Section 9.7.3 for more information. |
regexp_split_to_array('hello world', '\s+') |
{hello,world} |
|
setof text |
Split string using a POSIX regular expression asthe delimiter. See Section 9.7.3 for more information. |
regexp_split_to_table('hello world', '\s+') |
hello
(2 rows) |
|
text |
Repeat string the specifiednumber of times |
repeat('Pg', 4) |
PgPgPgPg |
|
text |
Replace all occurrences in string of substringfrom with substring to
|
replace('abcdefabcdef', 'cd', 'XX') |
abXXefabXXef |
|
text |
Return reversed string. | reverse('abcde') |
edcba |
|
text |
Return last n characters in the string. When n is negative, return all but first | n | characters.
|
right('abcde', 2) |
de |
|
text |
Fill up the string to lengthlength by appending the charactersfill (a space by default). If thestring is already longer thanlength then it is truncated.
|
rpad('hi', 5, 'xy') |
hixyx |
|
text |
Remove the longest string containing only characters fromcharacters (a space by default) from the end ofstring
|
rtrim('testxxzx', 'xyz') |
test |
|
text |
Split string on delimiter and return the given field (counting from one) |
split_part('abc~@~def~@~ghi', '~@~', 2) |
def |
|
int |
Location of specified substring (same asposition( , but note the reversedargument order) |
strpos('high', 'ig') |
2 |
|
text |
Extract substring (same assubstring( )
|
substr('alphabet', 3, 2) |
ph |
|
bool |
Returns true if string starts with prefix .
|
starts_with('alphabet', 'alph') |
t |
|
text |
Convert string to ASCII from another encoding(only supports conversion from LATIN1 , LATIN2 , LATIN9 ,and WIN1250 encodings)
|
to_ascii('Karel') |
Karel |
|
text |
Convert number to its equivalent hexadecimalrepresentation |
to_hex(2147483647) |
7fffffff |
|
text |
Any character in string that matches acharacter in the from set is replaced bythe corresponding character in the to set. If from is longer thanto , occurrences of the extra characters infrom are removed.
|
translate('12345', '143', 'ax') |
a2x5 |