用于将所有表和字段更改为MYSQL中的utf-8-bin归类的脚本
有一个SQL
或PHP
脚本,我可以运行这将更改数据库中的所有表和字段中的默认sorting规则?
我可以自己写一个,但我认为这应该是在这样的网站上容易获得的东西。 如果我能在有人发帖之前自己想出一个,我会自己发贴。
小心! 如果你实际上已经把utf作为另一种编码存储了,那么你的手上可能会有一些乱七八糟的东西。 先备份。 然后尝试一些标准的方法:
例如http://www.cesspit.net/drupal/node/898 http://www.hackszine.com/blog/archive/2007/05/mysql_database_migration_latin.html
我不得不求助于将所有文本字段转换为二进制,然后回到varchar /文本。 这已经救了我的屁股。
我有数据是UTF8,存储为latin1。 我做了什么:
删除索引。 将字段转换为二进制。 转换为utf8-general ci
如果你在LAMP上,在与db交互之前不要忘记添加设置NAMES命令,并且确保你设置了字符编docker。
可以在一个命令(而不是PHP的148)中完成:
mysql --database=dbname -B -N -e "SHOW TABLES" \ | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \ | mysql --database=dbname &
你必须爱命令行…(你可能需要使用mysql
的--user
和--password
选项)。
编辑:为了避免外键问题,增加了SET foreign_key_checks = 0;
和SET foreign_key_checks = 1;
我认为很容易做到这一点在两个步骤runin 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步:
这个查询将输出一个查询列表,每个查询列表一个。 您必须复制查询列表,然后将其粘贴到命令行或PhpMyAdmin的SQL选项卡以进行更改。
好的,我在写这篇文章的时候考虑了这个主题中所说的话。 感谢您的帮助,我希望这个脚本能帮助别人。 我对它的使用没有任何保证,所以请在运行之前备份。 它应该与所有数据库一起工作; 而且它在我自己的工作很好。
编辑:在顶部添加字符集/ collate转换为variables。 编辑2:更改数据库和表的默认字符集/ 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代码片段将改变数据库中所有表格的sorting规则。 (这是从这个网站 。)
<?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 />"; } } ?>
另一个使用命令行的方法,基于@ david的没有awk
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
美化
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
上面的脚本更完整的版本可以在这里find:
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
字符集和整理不是一回事。 sorting规则是关于如何对string进行sorting的一组规则。 字符集是关于如何表示字符的一组规则。 整理依赖于字符集。
在所有选定用于转换(使用SHOW TABLES
)的表中的脚本中,但在转换表之前检查表归类的更方便和便携的方式。 这个查询做到这一点:
SELECT table_name , table_collation FROM information_schema.tables
使用我的自定义shell collatedb ,它应该工作:
collatedb <username> <password> <database> <collation>
例如:
collatedb root 0000 myDatabase utf8_bin
感谢@nlaq的代码,这让我开始在下面的解决scheme。
我发布了一个WordPress插件,却没有意识到WordPress不会自动设置自动分页。 所以很多使用这个插件的人最终得到了latin1_swedish_ci
当它应该是utf8_general_ci
。
这里是我添加到插件来检测latin1_swedish_ci
collate并将其更改为utf8_general_ci
。
testing这个代码,然后在你自己的插件中使用它!
// 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();
一个简单的(愚蠢?:)解决scheme,使用您的IDE的多选function:
- 运行“SHOW TABLES”; 查询和复制结果列(表名)。
- 多选开始并添加“ALTER TABLE”。
- 多选结束并添加“CONVERT到CHARACTER SET UTF8 COLLATE utf8_general_ci;”
- 运行创build的查询。
如果您没有命令行访问权限或无法访问编辑INFORMATION_SCHEMA,则只需使用phpmyadmin即可完成此操作。
首先,听听许多其他答案的build议 – 你可以在这里搞砸了,所以做一个备份。 现在备份你的备份。 如果你的数据的编码方式与你要更改的不同,这也不太可能奏效。
请注意,您将需要查找在开始之前需要更改的有问题架构和字符编码的确切名称。
- 将数据库导出为SQL; 做一个副本; 在您select的文本编辑器中打开它
- 首先查找并replace模式,例如 – 查找: latin1_swedish_ci ,replace为: utf8_general_ci
- find并replace字符编码,如果你需要,例如 – find: latin1 ,replace: utf8
- 创build一个新的testing数据库,并将新的SQLfile upload到phpmyadmin
这是一个超级简单的方法,但是这不会改变数据的编码,所以只能在某些情况下使用。
我认为最快的方法是在控制台上使用phpmyadmin和一些jQuery。
转到表结构并打开Chrome / Firefox开发者控制台(通常键盘上的F12):
-
运行这个代码来select所有字段不正确的字段,并开始修改:
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正确的编码:
$("select[name*='field_collation']" ).val('utf8_general_ci');
-
保存
-
在“操作”选项卡的“整理”字段中更改表格的字符集
testingphpmyadmin 4.0和4.4,但我认为所有4.x版本的工作
我更新了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", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \ | mysql.exe -u [user] -p[password] --database=[database] &
用实际值replace[数据库],[用户]和[密码]占位符。
Git-bash用户可以下载这个bash脚本并轻松运行它。