Wie konvertiere ich alle Tabellen in der Datenbank in eine Sortierung?

82

Ich erhalte die Fehlermeldung:

Unzulässige Mischung von Kollatierungen (utf8_general_ci, IMPLICIT) und (utf8_unicode_ci, IMPLICIT) für die Operation '=' "

Ich habe versucht, beide Tabellen manuell zu ändern, erhalte utf8_general_ci,IMPLICITaber immer noch den Fehler.

Gibt es eine Möglichkeit, alle Tabellen zu konvertieren utf8_general_ci,IMPLICITund damit fertig zu werden?

lisovaccaro
quelle
Fand dies (hatte einige gute Antworten): stackoverflow.com/questions/105572/…
Luke Wyatt

Antworten:

166

Sie müssen für jede Tabelle eine alter table-Anweisung ausführen. Die Erklärung würde diesem Formular folgen:

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

Um nun alle Tabellen in der Datenbank abzurufen, müssen Sie die folgende Abfrage ausführen:

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

Lassen Sie MySQL nun den Code für Sie schreiben:

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";

Sie können die Ergebnisse kopieren und ausführen. Ich habe die Syntax nicht getestet, aber Sie sollten in der Lage sein, den Rest herauszufinden. Betrachten Sie es als eine kleine Übung.

Hoffentlich hilft das!

Namphibian
quelle
7
Für jemanden, der nach einer schnellen, perfekten Lösung sucht, habe ich Folgendes verwendet, um mit Tabellennamen als möglichen Schlüsselwörtern und natürlich mit Semikolons zu arbeiten :) CONCAT("ALTER TABLE `", TABLE_NAME,"` CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;")
Brian Leishman
3
Ich habe diese Abfrage mit abgeschlossen SELECT GROUP_CONCAT(ExecuteTheString SEPARATOR ' ') FROM (....) t, damit ich in phpMyAdmin alle Tabellen auf einmal leichter abrufen kann.
Zane
Dies gibt ein leeres Ergebnis in MySQL PHPMYAdmin zurück
Michael
@ Michael arbeitet immer noch für mich. Haben Sie die Parameter geändert, um Ihre Situation widerzuspiegeln?
Namphibian
@Namphibian nein ich ersetze nur das Schema durch mein eigenes Schema und Tabellentyp (InnoDB)
Michael
63

Bessere Option, um auch die Sortierung von Varchar-Spalten innerhalb der Tabelle zu ändern

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"

Zusätzlich, wenn Sie Daten mit einem Schlüssel in einer Spalte haben, die nicht utf8 ist, bevor Sie das Bündelskript verwenden

SET foreign_key_checks = 0;

Dies bedeutet, dass globales SQL für mySQL bestimmt ist:

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;

Aber seien Sie vorsichtig , wenn gemäß der MySQL-Dokumentation http://dev.mysql.com/doc/refman/5.1/en/charset-column.html ,

Wenn Sie ALTER TABLE verwenden, um eine Spalte von einem Zeichensatz in einen anderen zu konvertieren, versucht MySQL, die Datenwerte zuzuordnen. Wenn die Zeichensätze jedoch nicht kompatibel sind, kann es zu Datenverlust kommen. ""

BEARBEITEN: Speziell bei Aufzählung vom Spaltentyp stürzt die Aufzählung nur vollständig ab (auch wenn keine speziellen Zeichen vorhanden sind). Https://bugs.mysql.com/bug.php?id=26731

Florian HENRY - ATM-Beratung
quelle
27

@ Namphibians Vorschlag hat mir sehr geholfen ...
ging aber noch ein bisschen weiter und fügte dem Skript Spalten und Ansichten hinzu

Geben Sie einfach den Namen Ihres Schemas unten ein und der Rest wird erledigt

-- 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";
dGo
quelle
3
Ich habe Ihren Code zum Erfolg verwendet, danke. Ich würde empfehlen, die Aktivierung / Deaktivierung der Fremdschlüsselprüfung hinzuzufügen und auch Anführungszeichen um die Tabellenschlüssel hinzuzufügen.
Igor Skoric
1
Es ist nicht erforderlich, die Spalten einzeln ALTER TABLE CONVERT TO CHARACTER SET
SystemParadox
Funktioniert super. In meinem Fall hatte ich Tabelle / Spaltennamen zu zitieren Stichwort Konflikte (wie zu vermeiden Desc, Password..) zum Erfolg.
Deerchao
19

Unten ist die genauere Abfrage. Ich gebe ein Beispiel, wie man es in utf8 konvertiert

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"
Pankaj
quelle
Gut, aber ich musste es CONVERT TO CHARACTER SETfür Tabellen mit Daten
ändern
8

Sie können dieses BASH-Skript verwenden:

#!/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
Lukas Brzak
quelle
7

Wenn Sie PhpMyAdmin verwenden, können Sie jetzt:

  1. Wählen Sie die Datenbank aus.
  2. Klicken Sie auf die Registerkarte "Operationen".
  3. Wählen Sie im Abschnitt "Sortierung" die gewünschte Sortierung aus.
  4. Aktivieren Sie das Kontrollkästchen "Alle Tabellenkollatierungen ändern".
  5. Ein neues Kontrollkästchen "Alle Tabellenspaltenkollatierungen ändern" wird angezeigt.
  6. Aktivieren Sie das Kontrollkästchen "Alle Tabellenspaltenkollatierungen ändern".
  7. Klicken Sie auf die Schaltfläche "Los".

Ich musste über 250 Tabellen konvertieren. Es dauerte etwas mehr als 5 Minuten.

Mindsect-Team
quelle
3

Dies ist meine Version eines Bash-Skripts. Es verwendet den Datenbanknamen als Parameter und konvertiert alle Tabellen in einen anderen Zeichensatz und eine andere Sortierung (angegeben durch andere Parameter oder einen im Skript definierten Standardwert).

#!/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
)
Petr Stastny
quelle
3

Nehmen Sie die Antwort von @Petr Stastny noch einen Schritt weiter, indem Sie eine Passwortvariable hinzufügen. Ich würde es vorziehen, wenn es tatsächlich wie ein normales Passwort und nicht als Argument aufgenommen würde, aber es funktioniert für das, was ich brauchte.

#!/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"
GH
quelle
3

Für phpMyAdmin habe ich Folgendes herausgefunden:

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"

Ändern Sie einfach Ihren Tabellennamen und es geht Ihnen gut.

Calibra
quelle
@ LucaC. Sie müssen das Limit für group_concat erhöhen, z. B.:set session group_concat_max_len = @@max_allowed_packet;
James,
1

Wenn Sie ein Bash-Skript zum Kopieren und Einfügen benötigen:

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

Ändern Sie zabbix in Ihren Datenbanknamen.

Xdg
quelle
1

Im Anschluss an GH habe ich die Benutzer- und Hostparameter hinzugefügt, falls Sie dies auf einem Remote-Server tun müssen

    #!/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"
Tom Gould
quelle