Скрипт для изменения всех таблиц и полей на параметры сортировки utf-8-bin в MYSQL
есть SQL или PHP скрипт, который я могу запустить, что будет изменить параметры сортировки по умолчанию во всех таблицах и полях базы данных?
Я могу написать сам, но я думаю, что это должно быть что-то, что легко доступны на таком сайте. Если я смогу придумать его сам, прежде чем кто-то опубликует его, я сам его опубликую.
16 ответов:
будьте осторожны! Если у вас действительно есть utf, сохраненный как другая кодировка, у вас может быть настоящий беспорядок на ваших руках. Сначала назад. Затем попробуйте некоторые из стандартных методов:
например http://www.cesspit.net/drupal/node/898 http://www.hackszine.com/blog/archive/2007/05/mysql_database_migration_latin.html
Мне пришлось прибегнуть к преобразованию всех текстовых полей в двоичные, а затем обратно в varchar / text. Это спасло мою задницу.
У меня были данные UTF8, сохраненные как latin1. Что я сделал:
падение индексов. Преобразование полей в двоичные. Конвертировать в utf8-general ci
Если ваша лампа включена, не забудьте добавить команду set NAMES перед взаимодействием с БД и убедитесь, что вы установили заголовки кодировки символов.
может быть сделано в одной команде (а не 148 PHP):
mysql --database=dbname -B -N -e "SHOW TABLES" \ | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", , "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \ | mysql --database=dbname &вы должны любить командную строку... (Возможно, вам придется использовать
--userи--passwordвариантыmysql).EDIT: чтобы избежать проблем с внешним ключом, добавлено
SET foreign_key_checks = 0;иSET foreign_key_checks = 1;
Я думаю, что это легко сделать в два этапа запуска PhpMyAdmin.
Шаг 1:SELECT CONCAT('ALTER TABLE `', t.`TABLE_SCHEMA`, '`.`', t.`TABLE_NAME`, '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') as stmt FROM `information_schema`.`TABLES` t WHERE 1 AND t.`TABLE_SCHEMA` = 'database_name' ORDER BY 1Шаг 2:
Этот запрос выведет список запросов, по одному для каждой таблицы. Вы должны скопировать список запросов и вставить их в командную строку или на вкладку SQL PhpMyAdmin для внесения изменений.
ОК, я написал это с учетом того, что было сказано в этой теме. Спасибо за помощь, и я надеюсь, что этот скрипт поможет другим. У меня нет никаких гарантий на его использование, поэтому, пожалуйста, сделайте резервную копию перед его запуском. Это должны работа со всеми базами данных; и он отлично работал сам по себе.
EDIT: добавлены vars в верхней части, для которых charset / collate для преобразования. EDIT2: изменяет кодировку базы данных и таблиц по умолчанию / collate
<?php function MysqlError() { if (mysql_errno()) { echo "<b>Mysql Error: " . mysql_error() . "</b>\n"; } } $username = "root"; $password = ""; $db = "database"; $host = "localhost"; $target_charset = "utf8"; $target_collate = "utf8_general_ci"; echo "<pre>"; $conn = mysql_connect($host, $username, $password); mysql_select_db($db, $conn); $tabs = array(); $res = mysql_query("SHOW TABLES"); MysqlError(); while (($row = mysql_fetch_row($res)) != null) { $tabs[] = $row[0]; } // now, fix tables foreach ($tabs as $tab) { $res = mysql_query("show index from {$tab}"); MysqlError(); $indicies = array(); while (($row = mysql_fetch_array($res)) != null) { if ($row[2] != "PRIMARY") { $indicies[] = array("name" => $row[2], "unique" => !($row[1] == "1"), "col" => $row[4]); mysql_query("ALTER TABLE {$tab} DROP INDEX {$row[2]}"); MysqlError(); echo "Dropped index {$row[2]}. Unique: {$row[1]}\n"; } } $res = mysql_query("DESCRIBE {$tab}"); MysqlError(); while (($row = mysql_fetch_array($res)) != null) { $name = $row[0]; $type = $row[1]; $set = false; if (preg_match("/^varchar\((\d+)\)$/i", $type, $mat)) { $size = $mat[1]; mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARBINARY({$size})"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARCHAR({$size}) CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } else if (!strcasecmp($type, "CHAR")) { mysql_query("ALTER TABLE {$tab} MODIFY {$name} BINARY(1)"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARCHAR(1) CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } else if (!strcasecmp($type, "TINYTEXT")) { mysql_query("ALTER TABLE {$tab} MODIFY {$name} TINYBLOB"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} TINYTEXT CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } else if (!strcasecmp($type, "MEDIUMTEXT")) { mysql_query("ALTER TABLE {$tab} MODIFY {$name} MEDIUMBLOB"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} MEDIUMTEXT CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } else if (!strcasecmp($type, "LONGTEXT")) { mysql_query("ALTER TABLE {$tab} MODIFY {$name} LONGBLOB"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} LONGTEXT CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } else if (!strcasecmp($type, "TEXT")) { mysql_query("ALTER TABLE {$tab} MODIFY {$name} BLOB"); MysqlError(); mysql_query("ALTER TABLE {$tab} MODIFY {$name} TEXT CHARACTER SET {$target_charset}"); MysqlError(); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } if ($set) mysql_query("ALTER TABLE {$tab} MODIFY {$name} COLLATE {$target_collate}"); } // re-build indicies.. foreach ($indicies as $index) { if ($index["unique"]) { mysql_query("CREATE UNIQUE INDEX {$index["name"]} ON {$tab} ({$index["col"]})"); MysqlError(); } else { mysql_query("CREATE INDEX {$index["name"]} ON {$tab} ({$index["col"]})"); MysqlError(); } echo "Created index {$index["name"]} on {$tab}. Unique: {$index["unique"]}\n"; } // set default collate mysql_query("ALTER TABLE {$tab} DEFAULT CHARACTER SET {$target_charset} COLLATE {$target_collate}"); } // set database charset mysql_query("ALTER DATABASE {$db} DEFAULT CHARACTER SET {$target_charset} COLLATE {$target_collate}"); mysql_close($conn); echo "</pre>"; ?>
этот фрагмент PHP изменит параметры сортировки для всех таблиц в БД. (Это взято из этот сайт.)
<?php // your connection mysql_connect("localhost","root","***"); mysql_select_db("db1"); // convert code $res = mysql_query("SHOW TABLES"); while ($row = mysql_fetch_array($res)) { foreach ($row as $key => $table) { mysql_query("ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci"); echo $key . " => " . $table . " CONVERTED<br />"; } } ?>
другой подход с использованием командной строки, основанные на @Давида без
awkfor t in $(mysql --user=root --password=admin --database=DBNAME -e "show tables";);do echo "Altering" $t;mysql --user=root --password=admin --database=DBNAME -e "ALTER TABLE $t CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;";doneприукрашивали
for t in $(mysql --user=root --password=admin --database=DBNAME -e "show tables";); do echo "Altering" $t; mysql --user=root --password=admin --database=DBNAME -e "ALTER TABLE $t CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;"; done
более полную версию скрипта можно найти здесь:
http://www.zen-cart.com/index.php?main_page=product_contrib_info&products_id=1937
пожалуйста, оставьте отзыв об этом вкладе здесь:http://www.zen-cart.com/forum/showthread.php?p=1034214
кодировка и параметры сортировки не одно и то же. Параметры сортировки-это набор правил сортировки строк. Кодировка-это набор правил представления символов. Параметры сортировки зависят от кодировки.
в скриптах над всеми таблицами, выбранными для преобразования (с
SHOW TABLES), но более удобный и портативный способ проверить параметры сортировки таблицы перед преобразованием таблицы. Этот запрос делает это:SELECT table_name , table_collation FROM information_schema.tables
используйте мою пользовательскую оболочку collatedb, это должно работать :
collatedb <username> <password> <database> <collation>пример :
collatedb root 0000 myDatabase utf8_bin
спасибо @nlaq за код, который заставил меня начать на ниже Решение.
я выпустил плагин WordPress, не понимая, что WordPress не устанавливает параметры сортировки автоматически. Так что многие люди, использующие плагин в конечном итоге с
latin1_swedish_ciкогда это должно было бытьutf8_general_ci.вот код, который я добавил в плагин, чтобы обнаружить
latin1_swedish_ciсоберите и измените его наutf8_general_ci.проверьте этот код, прежде чем использовать его в своем собственном плагине!
// list the names of your wordpress plugin database tables (without db prefix) $tables_to_check = array( 'social_message', 'social_facebook', 'social_facebook_message', 'social_facebook_page', 'social_google', 'social_google_mesage', 'social_twitter', 'social_twitter_message', ); // choose the collate to search for and replace: $convert_fields_collate_from = 'latin1_swedish_ci'; $convert_fields_collate_to = 'utf8_general_ci'; $convert_tables_character_set_to = 'utf8'; $show_debug_messages = false; global $wpdb; $wpdb->show_errors(); foreach($tables_to_check as $table) { $table = $wpdb->prefix . $table; $indicies = $wpdb->get_results( "SHOW INDEX FROM `$table`", ARRAY_A ); $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `$table`" , ARRAY_A ); foreach($results as $result){ if($show_debug_messages)echo "Checking field ".$result['Field'] ." with collat: ".$result['Collation']."\n"; if(isset($result['Field']) && $result['Field'] && isset($result['Collation']) && $result['Collation'] == $convert_fields_collate_from){ if($show_debug_messages)echo "Table: $table - Converting field " .$result['Field'] ." - " .$result['Type']." - from $convert_fields_collate_from to $convert_fields_collate_to \n"; // found a field to convert. check if there's an index on this field. // we have to remove index before converting field to binary. $is_there_an_index = false; foreach($indicies as $index){ if ( isset($index['Column_name']) && $index['Column_name'] == $result['Field']){ // there's an index on this column! store it for adding later on. $is_there_an_index = $index; $wpdb->query( $wpdb->prepare( "ALTER TABLE `%s` DROP INDEX %s", $table, $index['Key_name']) ); if($show_debug_messages)echo "Dropped index ".$index['Key_name']." before converting field.. \n"; break; } } $set = false; if ( preg_match( "/^varchar\((\d+)\)$/i", $result['Type'], $mat ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARBINARY({$mat[1]})" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARCHAR({$mat[1]}) CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; } else if ( !strcasecmp( $result['Type'], "CHAR" ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` BINARY(1)" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARCHAR(1) CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; } else if ( !strcasecmp( $result['Type'], "TINYTEXT" ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TINYBLOB" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TINYTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; } else if ( !strcasecmp( $result['Type'], "MEDIUMTEXT" ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` MEDIUMBLOB" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` MEDIUMTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; } else if ( !strcasecmp( $result['Type'], "LONGTEXT" ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` LONGBLOB" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` LONGTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; } else if ( !strcasecmp( $result['Type'], "TEXT" ) ) { $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` BLOB" ); $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); $set = true; }else{ if($show_debug_messages)echo "Failed to change field - unsupported type: ".$result['Type']."\n"; } if($set){ if($show_debug_messages)echo "Altered field success! \n"; $wpdb->query( "ALTER TABLE `$table` MODIFY {$result['Field']} COLLATE $convert_fields_collate_to" ); } if($is_there_an_index !== false){ // add the index back. if ( !$is_there_an_index["Non_unique"] ) { $wpdb->query( "CREATE UNIQUE INDEX `{$is_there_an_index['Key_name']}` ON `{$table}` ({$is_there_an_index['Column_name']})", $is_there_an_index['Key_name'], $table, $is_there_an_index['Column_name'] ); } else { $wpdb->query( "CREATE UNIQUE INDEX `{$is_there_an_index['Key_name']}` ON `{$table}` ({$is_there_an_index['Column_name']})", $is_there_an_index['Key_name'], $table, $is_there_an_index['Column_name'] ); } } } } // set default collate $wpdb->query( "ALTER TABLE `{$table}` DEFAULT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" ); if($show_debug_messages)echo "Finished with table $table \n"; } $wpdb->hide_errors();
простой (тупой? :) решение, используя функцию множественного выбора вашей IDE:
- выполнить запрос" показать таблицы " и скопировать столбец результатов (имена таблиц).
- multi-select начала и добавить "ALTER TABLE".
- несколько выделенных окончаний и добавить " конвертировать в набор символов utf8 COLLATE utf8_general_ci;"
- выполнить созданных запросов.
вот простой способ сделать это с помощью только phpmyadmin, если у вас нет доступа к командной строке или доступа для редактирования INFORMATION_SCHEMA.
во - первых, прислушайтесь к советам многих других ответов здесь-вы действительно можете испортить здесь все, поэтому сделайте резервную копию. Теперь сделайте резервную копию вашей резервной копии. Также это вряд ли сработает, если ваши данные закодированы иначе, чем то, на что вы их меняете.
обратите внимание, что вам нужно будет найти точные имена схемы-нарушителя и кодировка символов, которую вам нужно изменить перед запуском.
- экспортируйте базу данных как SQL; сделайте копию; откройте ее в текстовом редакторе по вашему выбору
- сначала найдите и замените схему, например-find:latin1_swedish_ci заменить: utf8_general_ci
- найти и заменить символ кодировки, если вам нужно, например, найти: латинских типа 1 заменить: utf8
- создайте новую тестовую базу данных и загрузите новый файл SQL в phpmyadmin
Это супер простой способ сделать это, но опять же, это не изменить кодировку данных, поэтому он будет работать только в определенных обстоятельствах.
Я думаю, что самый быстрый способ - это phpmyadmin и некоторые jQuery на консоли.
перейдите к структуре таблицы и откройте консоль разработчика chrome/firefox (обычно F12 на клавиатуре):
запустите этот код, чтобы выбрать все поля с неправильной кодировкой и начать изменять:
var elems = $('dfn'); var lastID = elems.length - 1; elems.each(function(i) { if ($(this).html() != 'utf8_general_ci') { $('input:checkbox', $('td', $(this).parent().parent()).first()).attr('checked','checked'); } if (i == lastID) { $("button[name='submit_mult'][value='change']").click(); } });при загрузке страницы Используйте этот код на консоли, чтобы выбрать правильный кодировка:
$("select[name*='field_collation']" ).val('utf8_general_ci');сохранить
измените кодировку таблицы в поле "параметры сортировки" на вкладке "операция"
протестировано на phpmyadmin 4.0 и 4.4, но я думаю, что работа на всех 4.х версии
я обновил ответ nlaq для работы с PHP7 и правильной обработки многоколоночных индексов, двоичных сопоставленных данных (например,
latin1_bin) и т. д. и немного очистил код. Это единственный код, который я нашел / попробовал, который успешно перенес мою базу данных из latin1 в utf8.<?php /////////// BEGIN CONFIG //////////////////// $username = ""; $password = ""; $db = ""; $host = ""; $target_charset = "utf8"; $target_collation = "utf8_unicode_ci"; $target_bin_collation = "utf8_bin"; /////////// END CONFIG //////////////////// function MySQLSafeQuery($conn, $query) { $res = mysqli_query($conn, $query); if (mysqli_errno($conn)) { echo "<b>Mysql Error: " . mysqli_error($conn) . "</b>\n"; echo "<span>This query caused the above error: <i>" . $query . "</i></span>\n"; } return $res; } function binary_typename($type) { $mysql_type_to_binary_type_map = array( "VARCHAR" => "VARBINARY", "CHAR" => "BINARY(1)", "TINYTEXT" => "TINYBLOB", "MEDIUMTEXT" => "MEDIUMBLOB", "LONGTEXT" => "LONGBLOB", "TEXT" => "BLOB" ); $typename = ""; if (preg_match("/^varchar\((\d+)\)$/i", $type, $mat)) $typename = $mysql_type_to_binary_type_map["VARCHAR"] . "(" . (2*$mat[1]) . ")"; else if (!strcasecmp($type, "CHAR")) $typename = $mysql_type_to_binary_type_map["CHAR"] . "(1)"; else if (array_key_exists(strtoupper($type), $mysql_type_to_binary_type_map)) $typename = $mysql_type_to_binary_type_map[strtoupper($type)]; return $typename; } echo "<pre>"; // Connect to database $conn = mysqli_connect($host, $username, $password); mysqli_select_db($conn, $db); // Get list of tables $tabs = array(); $query = "SHOW TABLES"; $res = MySQLSafeQuery($conn, $query); while (($row = mysqli_fetch_row($res)) != null) $tabs[] = $row[0]; // Now fix tables foreach ($tabs as $tab) { $res = MySQLSafeQuery($conn, "SHOW INDEX FROM `{$tab}`"); $indicies = array(); while (($row = mysqli_fetch_array($res)) != null) { if ($row[2] != "PRIMARY") { $append = true; foreach ($indicies as $index) { if ($index["name"] == $row[2]) { $index["col"][] = $row[4]; $append = false; } } if($append) $indicies[] = array("name" => $row[2], "unique" => !($row[1] == "1"), "col" => array($row[4])); } } foreach ($indicies as $index) { MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` DROP INDEX `{$index["name"]}`"); echo "Dropped index {$index["name"]}. Unique: {$index["unique"]}\n"; } $res = MySQLSafeQuery($conn, "SHOW FULL COLUMNS FROM `{$tab}`"); while (($row = mysqli_fetch_array($res)) != null) { $name = $row[0]; $type = $row[1]; $current_collation = $row[2]; $target_collation_bak = $target_collation; if(!strcasecmp($current_collation, "latin1_bin")) $target_collation = $target_bin_collation; $set = false; $binary_typename = binary_typename($type); if ($binary_typename != "") { MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` MODIFY `{$name}` {$binary_typename}"); MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` MODIFY `{$name}` {$type} CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'"); $set = true; echo "Altered field {$name} on {$tab} from type {$type}\n"; } $target_collation = $target_collation_bak; } // Rebuild indicies foreach ($indicies as $index) { // Handle multi-column indices $joined_col_str = ""; foreach ($index["col"] as $col) $joined_col_str = $joined_col_str . ", `" . $col . "`"; $joined_col_str = substr($joined_col_str, 2); $query = ""; if ($index["unique"]) $query = "CREATE UNIQUE INDEX `{$index["name"]}` ON `{$tab}` ({$joined_col_str})"; else $query = "CREATE INDEX `{$index["name"]}` ON `{$tab}` ({$joined_col_str})"; MySQLSafeQuery($conn, $query); echo "Created index {$index["name"]} on {$tab}. Unique: {$index["unique"]}\n"; } // Set default character set and collation for table MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` DEFAULT CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'"); } // Set default character set and collation for database MySQLSafeQuery($conn, "ALTER DATABASE `{$db}` DEFAULT CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'"); mysqli_close($conn); echo "</pre>"; ?>
Для Пользователей Windows
В дополнение к ответу @ davidwinterbottom, пользователи windows могут использовать команду ниже:
mysql.exe --database=[database] -u [user] -p[password] -B -N -e "SHOW TABLES" \ | awk.exe '{print "SET foreign_key_checks = 0; ALTER TABLE", , "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \ | mysql.exe -u [user] -p[password] --database=[database] &заменить [база данных], [пользователь] и [пароль] заполнители с фактическими значениями.
Git-bash пользователи могут скачать этот bash script и просто запустить его.
Comments