如何将数据库中的所有表转换为一种排序规则?

Posted

技术标签:

【中文标题】如何将数据库中的所有表转换为一种排序规则?【英文标题】:How to convert all tables in database to one collation? 【发布时间】:2012-06-07 06:23:54 【问题描述】:

我收到错误:

用于操作“=”的排序规则 (utf8_general_ci,IMPLICIT) 和 (utf8_unicode_ci,IMPLICIT) 的非法混合

我尝试将这两个表手动更改为 utf8_general_ci,IMPLICIT,但仍然出现错误。

有没有办法将所有表格转换为utf8_general_ci,IMPLICIT 并完成它?

【问题讨论】:

找到这个(有一些很好的答案):***.com/questions/105572/… Click here for script and follow the steps 【参考方案1】:

您需要为每个表执行一个 alter table 语句。声明将遵循以下形式:

ALTER TABLE tbl_name
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]

现在要获取数据库中的所有表,您需要执行以下查询:

SELECT * 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="YourDataBaseName"
AND TABLE_TYPE="BASE TABLE";

所以现在让 mysql 为你编写代码:

SELECT CONCAT("ALTER TABLE ", TABLE_SCHEMA, '.', TABLE_NAME," COLLATE your_collation_name_here;") AS    ExecuteTheString
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="YourDatabaseName"
AND TABLE_TYPE="BASE TABLE";

您可以复制结果并执行它们。我没有测试语法,但你应该能够弄清楚其余的。把它想象成一个小练习。

希望有帮助!

【讨论】:

对于寻求快速完美解决方案的人,我使用以下方法将表名作为可能的关键字,当然还使用分号:) CONCAT("ALTER TABLE `", TABLE_NAME,"` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;") 我用SELECT GROUP_CONCAT(ExecuteTheString SEPARATOR ' ') FROM (....) t 包装了这个查询,这样我就可以在phpMyAdmin 中更轻松地一次获取所有表。 这会在 MySQL PHPMYAdmin 中返回一个空结果 @Michael 仍然为我工作。您是否更改了参数以反映您的情况? @Namphibian nope 我只用我自己的模式和表类型(InnoDB)替换模式【参考方案2】:

更好的选择也可以更改表内 varchar 列的排序规则

SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') AS    mySQL
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA= "myschema"
AND TABLE_TYPE="BASE TABLE"

另外,如果您在启动束脚本之前在非 utf8 列上有带有外键的数据,请使用

SET foreign_key_checks = 0;

这意味着全局 SQL 将用于 mySQL:

SET foreign_key_checks = 0;
ALTER TABLE `table1` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE `table2` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE `tableXXX` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
SET foreign_key_checks = 1;

但要注意是否根据mysql文档http://dev.mysql.com/doc/refman/5.1/en/charset-column.html

如果您使用 ALTER TABLE 将列从一个字符集转换为另一个,MySQL 会尝试映射数据值,但如果字符集不兼容,则可能会丢失数据。 "

编辑:特别是对于列类型枚举,它只会使枚举集完全崩溃(即使没有特殊字符) https://bugs.mysql.com/bug.php?id=26731

【讨论】:

在尝试了许多解决方案之后,这是迄今为止最好的答案,而且效果很好!【参考方案3】:

@Namphibian 的建议对我帮助很大... 不过更进一步,在脚本中添加了列和视图

只需在下面输入您的架构名称,剩下的就交给它了

-- set your table name here
SET @MY_SCHEMA = "";

-- tables
SELECT DISTINCT
    CONCAT("ALTER TABLE ", TABLE_NAME," CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as queries
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA=@MY_SCHEMA
  AND TABLE_TYPE="BASE TABLE"

UNION

-- table columns
SELECT DISTINCT
    CONCAT("ALTER TABLE ", C.TABLE_NAME, " CHANGE ", C.COLUMN_NAME, " ", C.COLUMN_NAME, " ", C.COLUMN_TYPE, " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as queries
FROM INFORMATION_SCHEMA.COLUMNS as C
    LEFT JOIN INFORMATION_SCHEMA.TABLES as T
        ON C.TABLE_NAME = T.TABLE_NAME
WHERE C.COLLATION_NAME is not null
    AND C.TABLE_SCHEMA=@MY_SCHEMA
    AND T.TABLE_TYPE="BASE TABLE"

UNION

-- views
SELECT DISTINCT
    CONCAT("CREATE OR REPLACE VIEW ", V.TABLE_NAME, " AS ", V.VIEW_DEFINITION, ";") as queries
FROM INFORMATION_SCHEMA.VIEWS as V
    LEFT JOIN INFORMATION_SCHEMA.TABLES as T
        ON V.TABLE_NAME = T.TABLE_NAME
WHERE V.TABLE_SCHEMA=@MY_SCHEMA
    AND T.TABLE_TYPE="VIEW";

【讨论】:

我用你的代码成功了,谢谢。我建议添加外键检查启用/禁用,并在表键周围添加引号。 不需要单独做列,ALTER TABLE CONVERT TO CHARACTER SET 会自动转换所有列 效果很好。就我而言,我必须引用表/列名以避免关键字冲突(例如DescPassword..)才能成功。【参考方案4】:

以下是更准确的查询。 我正在举例说明如何将其转换为 utf8

SELECT CONCAT("ALTER TABLE `", TABLE_NAME,"` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;") AS    mySQL
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="myschema"
AND TABLE_TYPE="BASE TABLE"

【讨论】:

很好,但我需要将其更改为 CONVERT TO CHARACTER SET 以用于包含数据的表格【参考方案5】:

如果您使用的是 PhpMyAdmin,您现在可以:

    选择数据库。 点击“操作”标签。 在“排序规则”部分下,选择所需的排序规则。 点击“更改所有表格排序规则”复选框。 将出现一个新的“更改所有表格列排序规则”复选框。 点击“更改所有表格列排序规则”复选框。 点击“开始”按钮。

我有超过 250 个表格要转换。花了 5 多分钟。

【讨论】:

【参考方案6】:

你可以使用这个 BASH 脚本:

#!/bin/bash

USER="YOUR_DATABASE_USER"
PASSWORD="YOUR_USER_PASSWORD"
DB_NAME="DATABASE_NAME"
CHARACTER_SET="utf8" # your default character set
COLLATE="utf8_general_ci" # your default collation

tables=`mysql -u $USER -p$PASSWORD -e "SELECT tbl.TABLE_NAME FROM information_schema.TABLES tbl WHERE tbl.TABLE_SCHEMA = '$DB_NAME' AND tbl.TABLE_TYPE='BASE TABLE'"`

for tableName in $tables; do
    if [[ "$tableName" != "TABLE_NAME" ]] ; then
        mysql -u $USER -p$PASSWORD -e "ALTER TABLE $DB_NAME.$tableName DEFAULT CHARACTER SET $CHARACTER_SET COLLATE $COLLATE;"
        echo "$tableName - done"
    fi
done

【讨论】:

【参考方案7】:

对于 phpMyAdmin,我想通了:

SELECT GROUP_CONCAT("ALTER TABLE ", TABLE_SCHEMA, '.', TABLE_NAME," CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" SEPARATOR ' ') AS    OneSQLString
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="yourtableschemaname"
AND TABLE_TYPE="BASE TABLE"

只需更改您的tableschemaname 就可以了。

【讨论】:

@LucaC。您需要增加 group_concat 限制例如:set session group_concat_max_len = @@max_allowed_packet;【参考方案8】:

这是我的 bash 脚本版本。它将数据库名称作为参数,并将所有表转换为另一个字符集和排序规则(由脚本中定义的另一个参数或默认值给出)。

#!/bin/bash

# mycollate.sh <database> [<charset> <collation>]
# changes MySQL/MariaDB charset and collation for one database - all tables and
# all columns in all tables

DB="$1"
CHARSET="$2"
COLL="$3"

[ -n "$DB" ] || exit 1
[ -n "$CHARSET" ] || CHARSET="utf8mb4"
[ -n "$COLL" ] || COLL="utf8mb4_general_ci"

echo $DB
echo "ALTER DATABASE $DB CHARACTER SET $CHARSET COLLATE $COLL;" | mysql

echo "USE $DB; SHOW TABLES;" | mysql -s | (
    while read TABLE; do
        echo $DB.$TABLE
        echo "ALTER TABLE $TABLE CONVERT TO CHARACTER SET $CHARSET COLLATE $COLL;" | mysql $DB
    done
)

【讨论】:

【参考方案9】:

通过添加密码变量更进一步地从@Petr Stastny 那里得到答案。如果它实际上像常规密码一样而不是作为参数,我更喜欢它,但它可以满足我的需要。

#!/bin/bash

# mycollate.sh <database> <password> [<charset> <collation>]
# changes MySQL/MariaDB charset and collation for one database - all tables and
# all columns in all tables

DB="$1"
PW="$2"
CHARSET="$3"
COLL="$4"

[ -n "$DB" ] || exit 1
[ -n "$PW" ]
[ -n "$CHARSET" ] || CHARSET="utf8mb4"
[ -n "$COLL" ] || COLL="utf8mb4_bin"

PW="--password=""$PW"

echo $DB
echo "ALTER DATABASE $DB CHARACTER SET $CHARSET COLLATE $COLL;" | mysql -u root "$PW"

echo "USE $DB; SHOW TABLES;" | mysql -s "$PW" | (
    while read TABLE; do
        echo $DB.$TABLE
        echo "ALTER TABLE $TABLE CONVERT TO CHARACTER SET $CHARSET COLLATE $COLL;" | mysql "$PW" $DB
    done
)

PW="pleaseEmptyMeNow"

【讨论】:

【参考方案10】:

从 G H 开始,我添加了用户和主机参数,以防您需要在远程服务器上执行此操作

    #!/bin/bash

    # mycollate.sh <database> <user> <password> [<host> <charset> <collation>]
    # changes MySQL/MariaDB charset and collation for one database - all tables and
    # all columns in all tables

    DB="$1"
    USER="$2"
    PW="$3"
    HOST="$4"
    CHARSET="$5"
    COLL="$6"

    [ -n "$DB" ] || exit 1
    [ -n "$USER" ] || exit 1
    [ -n "$PW" ] || exit 1
    [ -n "$HOST" ] || HOST="localhost"
    [ -n "$CHARSET" ] || CHARSET="utf8mb4"
    [ -n "$COLL" ] || COLL="utf8mb4_general_ci"

    PW="--password=""$PW"
    HOST="--host=""$HOST"
    USER="--user=""$USER"

    echo $DB
    echo "ALTER DATABASE $DB CHARACTER SET $CHARSET COLLATE $COLL;" | mysql "$HOST" "$USER" "$PW"

    echo "USE $DB; SHOW TABLES;" | mysql  "$HOST" "$USER" "$PW" | (
        while read TABLE; do
            echo $DB.$TABLE
            echo "ALTER TABLE $TABLE CONVERT TO CHARACTER SET $CHARSET COLLATE $COLL;" | mysql  "$HOST" "$USER" "$PW" $DB
        done
    )

    PW="pleaseEmptyMeNow"

【讨论】:

【参考方案11】:

如果你想要一个复制粘贴 bash 脚本:

var=$(mysql -e 'SELECT CONCAT("ALTER TABLE ", TABLE_NAME," CONVERT TO CHARACTER SET utf8 COLLATE utf8_czech_ci;") AS execTabs FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="zabbix" AND TABLE_TYPE="BASE TABLE"' -uroot -p )

var+='ALTER DATABASE zabbix CHARACTER SET utf8 COLLATE utf8_general_ci;'

echo $var | cut -d " " -f2- | mysql -uroot -p zabbix

将 zabbix 更改为您的数据库名称。

【讨论】:

以上是关于如何将数据库中的所有表转换为一种排序规则?的主要内容,如果未能解决你的问题,请参考以下文章

如何将排序规则更改为数据库的所有列?

如何将整个 MySQL 数据库字符集和排序规则转换为 UTF-8?

SQL Server转换数据库的排序规则

SQL server中的物理排序和逻辑排序是怎么回事

SQL Server 2005 排序规则问题

SQL Server - 将 varchar 转换为另一个排序规则(代码页)以修复字符编码