web-dev-qa-db-de.com

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

Ich bekomme einen Fehler:

Ungültige Mischung aus Kollatierungen (utf8_general_ci, IMPLICIT) und (utf8_unicode_ci, IMPLICIT) für Operation '=' "

Ich habe versucht, beide Tabellen manuell in utf8_general_ci,IMPLICIT zu ändern, aber ich bekomme immer noch den Fehler.

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

58
lisovaccaro

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

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

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

Nun lassen Sie MySQL 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!

130
Namphibian

Besser ist es auch, die Sortierung der varchar-Spalten in 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 forein key in der Spalte non utf8 haben, bevor Sie das Bündelskript starten 

SET foreign_key_checks = 0;

Dies bedeutet, dass globales SQL für mySQL gilt:

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 Sie der Dokumentation zu mysql http://dev.mysql.com/doc/refman/5.1/de/charset-column.html folgen. 

Wenn Sie mit ALTER TABLE eine Spalte von einem Zeichensatz in einen anderen konvertieren, versucht MySQL, die Datenwerte zuzuordnen. Wenn die Zeichensätze jedoch nicht kompatibel sind, kann dies zu Datenverlust führen. "

BEARBEITEN: Speziell für den Typ der Spalte Typ, stürzt der Satz vollständig ab (auch wenn keine Sonderzeichen vorhanden sind) https://bugs.mysql.com/bug.php?id=26731

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"
17
Pankaj Soni

@ Namphibians Vorschlag hat mir sehr geholfen ...
ging jedoch etwas weiter und fügte dem Skript Spalten und Ansichten hinzu

geben Sie einfach den Namen Ihres Schemas 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 [email protected]_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 [email protected]_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 [email protected]_SCHEMA
    AND T.TABLE_TYPE="VIEW";
15
dGo

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
5
Lukas Brzak

Wenn Sie ein Bash-Skript zum Kopieren und Einfügen wünschen:

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.

0
Xdg

Im Anschluss an G H habe ich die Benutzer- und Host-Parameter 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"
0
Tom Gould

Gehen Sie die Antwort von @Petr Stastny noch einen Schritt weiter, indem Sie eine Kennwortvariable hinzufügen. Ich würde es vorziehen, wenn es tatsächlich als normales Passwort und nicht als Argument angenommen 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"
0
G H

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 (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
)
0
Petr Stastny