Як перетворити всі таблиці в базі даних на одне порівняння?


82

Я отримую помилку:

Незаконне поєднання зіставок (utf8_general_ci, IMPLICIT) та (utf8_unicode_ci, IMPLICIT) для роботи '=' "

Я спробував змінити обидві таблиці вручну на, utf8_general_ci,IMPLICITале я все ще отримую помилку.

Чи є спосіб перетворити всі таблиці utf8_general_ci,IMPLICITі закінчити з цим?


Знайшов це (мав кілька хороших відповідей): stackoverflow.com/questions/105572/…
Luke Wyatt 02

Відповіді:


166

Вам потрібно виконати оператор 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";

Ви можете скопіювати результати та виконати їх. Я не перевіряв синтаксис, але ви зможете зрозуміти решту. Подумайте про це як про невелику вправу.

Надія, що допомагає!


7
Для тих, хто шукає швидкого ідеального рішення, я використовував наступне, щоб працювати з іменами таблиць, які є можливими ключовими словами, і, звичайно, з крапкою з комою :) CONCAT("ALTER TABLE `", TABLE_NAME,"` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;")
Брайан Лейшман

3
Я обернув цей запит, SELECT GROUP_CONCAT(ExecuteTheString SEPARATOR ' ') FROM (....) tщоб я міг легше захопити всі таблиці одночасно у phpMyAdmin.
Зейн

Це повертає порожній результат у MySQL PHPMYAdmin
Майкл

@Michael все ще працює для мене. Ви змінили параметри, щоб відображати вашу ситуацію?
Намфібія

@Namphibian nope, я лише замінюю схему на власну схему та тип таблиці (InnoDB)
Майкл

63

Кращий варіант також змінити сортування стовпців 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"

До того ж, якщо у вас є дані з ключем forein у стовпці non 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


27

Пропозиція @ 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";

3
Я використав ваш код для успіху, дякую. Я б рекомендував додати перевірку зовнішнього ключа увімкнути / вимкнути, а також додати лапки навколо ключів таблиці.
Ігор Скоріч

1
Не потрібно робити стовпці окремо, оскільки ALTER TABLE CONVERT TO CHARACTER SETавтоматично перетворює всі стовпці
SystemParadox,

Чудово працює. У моєму випадку мені довелося цитувати імена таблиць / стовпців, щоб уникнути конфлікту ключових слів (наприклад Desc, Password..) до успіху.
deerchao

19

Нижче наведено більш точний запит. Я наводжу приклад, як перетворити його на 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таблиці з даними
user11153

8

Ви можете використовувати цей сценарій 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, тепер ви можете:

  1. Виберіть базу даних.
  2. Клацніть на вкладку "Операції".
  3. У розділі "Сортування" виберіть бажаний порядок.
  4. Установіть прапорець "Змінити сортування всіх таблиць".
  5. З'явиться новий прапорець "Змінити порівняння всіх стовпців таблиць".
  6. Установіть прапорець "Змінити сортування всіх стовпців таблиць".
  7. Натисніть кнопку "Перейти".

У мене було понад 250 таблиць для перетворення. Це зайняло трохи більше 5 хвилин.


4

Для 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"

Просто змініть ім'я таблиціchema і все в порядку.


@LucaC. вам потрібно збільшити обмеження group_concat напр .:set session group_concat_max_len = @@max_allowed_packet;
Джеймс

3

Це моя версія скрипта 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
)

3

Отримавши відповідь від @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"

1

Якщо ви хочете скопіювати-вставте скрипт 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 на ім'я вашої бази даних.


1

Далі від GH я додав параметри користувача та хосту, якщо це потрібно зробити на віддаленому сервері

    #!/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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.