Биллинговая система Nodeny
22 Ноября 2024, 23:01:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Прекращена поддержка версии Nodeny 49
 
   Начало   Помощь Поиск Войти Регистрация  
Страниц: [1]
  Печать  
Автор Тема: Конвертация базы из latin1 в cp1251  (Прочитано 23097 раз)
versus
Администратор
Спец
*****

Карма: 21
Offline Offline

Сообщений: 845


44306843
Просмотр профиля WWW Email
« : 29 Сентября 2009, 21:37:18 »

Описание проблемы

Допустим, у Вас есть база данных MySQL с кодировкой latin1. В ней не работает сортировка, русский текст не видно в phpMyAdmin и так далее. Вы хотите перевести её в правильную кодировку — cp1251, в которой фактически и находятся данные в базе. Однако простого способа это сделать нет.
[править] Решение

    * Делаем полный бэкап базы.

    * С помощью скрипта fixmyenc, текст которого приводится ниже, выполняем следующее:

perl fixmyenc HOST DATABASE USER PASSWORD >fixdb.sql

Если не происходит никаких ошибок, создаётся файл fixdb.sql — скрипт на языке sql, которым мы и будем чинить базу.

    * (необязательно) Просматриваем созданный файл.

    * Выполняем содержащиеся в нём SQL-запросы:

mysql --host=HOST --database=DATABASE --user=USER --password=PASSWORD <fixdb.sql

    * Если и на этом этапе нет никаких ошибок — значит наша база успешно перекодирована. Если ошибки были — восстанавливаем базу из бэкапа, созданного перед началом работы, и сообщаем об ошибке (с её полным текстом) например на страницу обсуждения.

Важно: Скрипт fixmyenc написан так, что при малейшей проблеме останавливает свою работу с ошибкой и не создаёт sql-скрипта. Это сделано специально (и не составляет проблемы, поскольку в самой базе при этом ничего не меняется), однако о каждой такой проблеме тоже очень желательно сообщить. После сообщения об ошибке скрипт будет исправлен и новый текст выложен здесь же.
[править] Принцип работы

    * Все полнотекстовые индексы (FULLTEXT KEY) удаляются и в конце пересоздаются.
    * CHARACTER SET и COLLATION самой базы, всех таблиц и всех текстовых полей в таблицах меняются сначала с latin1 на binary, а затем с binary на cp1251_general_ci (если бы мы попытались изменить кодировку напрямую из latin1 в cp1251, то MySQL не нашёл бы символов, соответствующих верхней части latin1, в cp1251, и просто заменил бы их знаками вопроса, в результате чего все русские буквы были бы безвозвратно потеряны).

Текст скрипта fixmyenc

#!/usr/bin/perl
use warnings;
use strict;
use DBI;
unless( 4 == @ARGV ) {
   print STDERR "Usage: $0 <host> <database> <user> <password>\n";
   exit 1;
}
my ($host, $database, $user, $password) = @ARGV;
die "bad host/db/user" unless $host =~ /^[\w\-\.]+$/ and $database =~ /^[\w_]+$/ and $user =~ /^[\w_]+$/;
my $dbh = DBI->connect("DBI:mysql:database=$database;host=$host", $user, $password, {'RaiseError' => 1});
my (@pass0, @pass1, @pass2, @pass3) = ();
my $sth = $dbh->prepare("SHOW CREATE DATABASE $database");
$sth->execute;
my @arr = $sth->fetchrow_array;
$arr[1] =~ /^CREATE DATABASE `$database` \/\*!\d+ DEFAULT CHARACTER SET latin1( COLLATE latin1_\w+)? \*\/$/
   or die "bad database spec: $arr[1]";
push @pass1, "ALTER DATABASE `$database` DEFAULT CHARACTER SET binary";
push @pass2, "ALTER DATABASE `$database` DEFAULT CHARACTER SET cp1251 COLLATE cp1251_general_ci";

$sth = $dbh->prepare("SHOW TABLES");
$sth->execute;
my @tables = ();
while( my @row = $sth->fetchrow_array ) {
   die "bad table name: $row[0]" unless $row[0] =~ /^[\w_]+$/;
   push @tables, $row[0];
}

foreach my $table (@tables) {
   $sth = $dbh->prepare("SHOW CREATE TABLE `$table`");
   $sth->execute;
   my @row = $sth->fetchrow_array;
   $row[1] =~ s/ COMMENT='[^'\\]*'$//s;
   $row[1] =~ /^CREATE TABLE `$table` \(.*\)([^)]+)$/s
      or die "bad table spec: $row[1]";
   my $tail = $1;
   unless( $tail =~ /\bDEFAULT CHARSET=latin1\b/ ) {
      die "bad table $table spec tail: $tail";
   }
   push @pass1, "ALTER TABLE `$table` DEFAULT CHARSET binary";
   push @pass2, "ALTER TABLE `$table` DEFAULT CHARSET cp1251 COLLATE cp1251_general_ci";
   my (%fulltext, %column_in_fulltext_indexes, %remove_fulltext_indexes) = ();
   $sth = $dbh->prepare("SHOW INDEX FROM `$table`");
   $sth->execute;
   while( my $row = $sth->fetchrow_hashref ) {
      next unless $row->{Index_type} eq "FULLTEXT";
      $fulltext{$row->{Key_name}} ||= [];
      $fulltext{$row->{Key_name}}[$row->{Seq_in_index}-1] = $row->{Column_name};
      $column_in_fulltext_indexes{$row->{Column_name}} ||= [];
      push @{$column_in_fulltext_indexes{$row->{Column_name}}}, $row->{Key_name};
   }
   $sth = $dbh->prepare("SHOW FULL COLUMNS FROM `$table`");
   $sth->execute;
   while( my @row = $sth->fetchrow_array ) {
      my ($column, $type, $collation) = @row[0,1,2];
      if( defined $collation and "NULL" ne $collation ) {
         die "bad collation in column $column of table $table: $collation" unless $collation =~ /^latin1_\w+$/;
         push @pass1, "ALTER TABLE `$table` MODIFY COLUMN `$column` $type CHARACTER SET binary";
         push @pass2, "ALTER TABLE `$table` MODIFY COLUMN `$column` $type CHARACTER SET  cp1251 COLLATE cp1251_general_ci";
         foreach my $index (@{$column_in_fulltext_indexes{$column}}) {
            $remove_fulltext_indexes{$index} = 1;
         }
      }
   }
   foreach my $index (keys %remove_fulltext_indexes) {
      push @pass0, "ALTER TABLE `$table` DROP INDEX `$index`";
      push @pass3, "ALTER TABLE `$table` ADD FULLTEXT INDEX `$index` (" . join( ",", map { "`$_`" } @{$fulltext{$index}} ) . ")";
   }
}

print join ";\n", "USE `$database`", @pass0, @pass1, @pass2, @pass3, "";
Записан
versus
Администратор
Спец
*****

Карма: 21
Offline Offline

Сообщений: 845


44306843
Просмотр профиля WWW Email
« Ответ #1 : 29 Сентября 2009, 21:38:49 »

Взято отсюда

http://www.1gb.ru/wiki/index.php?title=%D0%98%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8_MySQL-%D0%B1%D0%B0%D0%B7%D1%8B_%D1%81_latin1_%D0%BD%D0%B0_cp1251 
Записан
slava
NoDeny
Пользователь
*

Карма: 0
Offline Offline

Сообщений: 26


Просмотр профиля Email
« Ответ #2 : 11 Декабря 2010, 23:22:35 »

запускаю так perl fixmyenc localhost bill user pass >> fixdb.sql
выдает ошибку:

bad table spec: CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `dopdata` AS select `f`.`id` AS `id`,`f`.`template_num` AS `template_num`,`f`.`parent_type` AS `parent_type`,`f`.`field_type` AS `field_type`,`f`.`field_name` AS `field_name`,`f`.`field_alias` AS `field_alias`,`f`.`field_flags` AS `field_flags`,`f`.`field_template` AS `field_template`,`f`.`comment` AS `comment`,`v`.`line_id` AS `line_id`,`v`.`parent_id` AS `parent_id`,`v`.`dopfield_id` AS `dopfield_id`,`v`.`field_value` AS `field_value`,`v`.`admin_id` AS `admin_id`,`v`.`time` AS `time`,`v`.`revision` AS `revision` from (`dopfields` `f` left join `dopvalues` `v` on((`f`.`id` = `v`.`dopfield_id`))) at fixmyenc line 35.
Записан
kompnm
Пользователь
**

Карма: 1
Offline Offline

Сообщений: 6


Просмотр профиля Email
« Ответ #3 : 12 Мая 2011, 16:50:13 »

Давно была такая проблема решение тут http://device.net.ua/forum/viewtopic.php?f=11&t=207

1.качаем Sypex Dumper Lite отсюда http://sypex.net/
2.выкладываем его на хост источник (например ***.net.ua/dumper.php)
3.запускаем скрипт http://***.net.ua/dumper.php
4.подключаемся к базе и копируем его на локальный компьютер 5.Открываем его в WordPad - смотрим чтобы буквы были русские а не крокозябры.
6.В WordPad выбираем заменить latin1 на cp1251 - заменяем всё. 7.Сохраняем в фаил с любым именем
8.На хостинге приёмнике делаем импорт получившегося файла в кодировке cp1251
Записан
ser970
NoDeny
Спец
*

Карма: 70
Offline Offline

Сообщений: 1323

262462619
Просмотр профиля Email
« Ответ #4 : 16 Мая 2011, 07:27:13 »

Давно была такая проблема решение тут http://device.net.ua/forum/viewtopic.php?f=11&t=207

1.качаем Sypex Dumper Lite отсюда http://sypex.net/
2.выкладываем его на хост источник (например ***.net.ua/dumper.php)
3.запускаем скрипт http://***.net.ua/dumper.php
4.подключаемся к базе и копируем его на локальный компьютер 5.Открываем его в WordPad - смотрим чтобы буквы были русские а не крокозябры.
6.В WordPad выбираем заменить latin1 на cp1251 - заменяем всё. 7.Сохраняем в фаил с любым именем
8.На хостинге приёмнике делаем импорт получившегося файла в кодировке cp1251
накой все так слажно - man iconv - все есть в портах и делается на одной машине

Записан
versus
Администратор
Спец
*****

Карма: 21
Offline Offline

Сообщений: 845


44306843
Просмотр профиля WWW Email
« Ответ #5 : 17 Мая 2011, 12:27:24 »

Я тоже так думал, пока не пришлось переконверчивать базу мускула. Во был секс...
Записан
VitalVas
NoDeny
Спец
*

Карма: 60
Offline Offline

Сообщений: 991



Просмотр профиля WWW
« Ответ #6 : 17 Мая 2011, 13:40:12 »

Я тоже так думал, пока не пришлось переконверчивать базу мускула. Во был секс...
+1
iconv немного криво конвертирует....
Записан
Страниц: [1]
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.20 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!