Скрипт для изменения всех таблиц и полей для сопоставления utf-8-bin в MYSQL - PullRequest
56 голосов
/ 20 сентября 2008

Существует ли сценарий SQL или PHP, который я могу запустить, который изменит параметры сортировки по умолчанию во всех таблицах и полях базы данных?

Я могу написать сам, но я думаю, что это должно быть легко доступно на таком сайте, как этот. Если я смогу придумать его сам, прежде чем кто-то его опубликует, я опубликую его сам.

Ответы [ 16 ]

85 голосов
/ 21 марта 2009

Может быть сделано одной командой (вместо 148 PHP):

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 &

Ты должен любить командную строку ... (Возможно, вам придется использовать опции --user и --password для mysql).

РЕДАКТИРОВАТЬ: чтобы избежать проблем с внешним ключом, добавлены SET foreign_key_checks = 0; и SET foreign_key_checks = 1;

39 голосов
/ 22 июня 2010

Я думаю, что это легко сделать в два этапа, запустив 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 для внесения изменений.

27 голосов
/ 20 сентября 2008

ОК, я написал это с учетом того, что было сказано в этой теме. Спасибо за помощь, и я надеюсь, что этот скрипт поможет другим. У меня нет никаких гарантий на его использование, поэтому, пожалуйста, BACKUP, прежде чем запускать его. должен работать со всеми базами данных; и он отлично работал самостоятельно.

РЕДАКТИРОВАТЬ: Вверху добавлены переменные, для которых нужно преобразовать кодировку / сопоставление EDIT2: изменяет кодировку / сопоставление по умолчанию для базы данных и таблиц

<code><?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 "
"; ?>
24 голосов
/ 20 сентября 2008

Будь осторожен! Если вы на самом деле храните 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

Если вы используете LAMP, не забудьте добавить команду set NAMES перед взаимодействием с БД и убедитесь, что вы установили заголовки кодировки символов.

14 голосов
/ 20 сентября 2008

Этот фрагмент 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 . " =&gt; " . $table . " CONVERTED<br />";
    }
}
?> 
4 голосов
/ 18 апреля 2013

Другой подход с использованием командной строки, основанный на @ david's без 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

prettified

  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
2 голосов
/ 03 июня 2011

Более полную версию скрипта выше можно найти здесь:

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

1 голос
/ 03 июня 2012

В сценариях выше всех таблиц, выбранных для преобразования (с SHOW TABLES), но более удобный и портативный способ проверки сопоставления таблиц перед преобразованием таблицы. Этот запрос делает это:

SELECT table_name
     , table_collation 
FROM information_schema.tables
1 голос
/ 20 сентября 2008

Charset и сопоставление - это не одно и то же. Сортировка - это набор правил сортировки строк. Кодировка - это набор правил представления символов. Сортировка зависит от кодировки.

0 голосов
/ 06 мая 2017

Для пользователей 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] &

Замените заполнители [база данных], [пользователь] и [пароль] действительными значениями.

Git-bash пользователи могут загрузить этот bash-скрипт и легко его запустить.

...