วิธีการเปลี่ยนการเรียงของฐานข้อมูลตารางคอลัมน์?


201

ฐานข้อมูลคือ latin1_general_ciutf8mb4_general_ciและตอนนี้ฉันต้องการที่จะเปลี่ยนการเปรียบเทียบที่จะ

มีการตั้งค่าใด ๆ ใน PhpMyAdmin เพื่อเปลี่ยนการจัดเรียงฐานข้อมูลตารางคอลัมน์หรือไม่? แทนที่จะเปลี่ยนทีละคน?


3
ดูคำตอบนี้ได้ที่: stackoverflow.com/questions/5906585/…
Timo Huovinen

คำตอบ:


260

คุณต้องทำการแปลงทีละโต๊ะ:

ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 

(ซึ่งจะแปลงคอลัมน์ก็เช่นกัน) หรือส่งออกฐานข้อมูลที่มีและนำกลับมาพร้อมกับlatin1utf8mb4


15
แต่ฉันต้องการเปลี่ยนการเรียงคอลัมน์ สิ่งนี้จะเปลี่ยนเฉพาะการจัดเรียงตาราง ..
user158469

7
@rsensan: CONVERTจะเปลี่ยนการจัดเรียงของคอลัมน์เช่นกัน
Quassnoi

21
database ชุดอักขระการเปลี่ยนแปลงค่าเริ่มต้นของ utf8 ค่าเริ่มต้นการรวมค่า utf8_general_ci;
stormwild

8
@stormwild: สิ่งนี้จะไม่ส่งผลกระทบต่อตารางที่มีอยู่
Quassnoi

47
ข้อความค้นหาของฉัน: แก้ไขตารางMYTABLEแปลงเป็นชุดอักขระ utf8mb4 COLLATE utf8mb4_unicode_ci; โปรดอย่าใช้ utf8_general_ci อีกต่อไป ;-)
Kapitein Witbaard

213

ฉันมีส่วนร่วมที่นี่เป็น OP ถาม:

วิธีการเปลี่ยนการเรียงของฐานข้อมูลตารางคอลัมน์?

คำตอบที่เลือกเพียงระบุไว้ในระดับตาราง


เปลี่ยนความกว้างของฐานข้อมูล:

ALTER DATABASE <database_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

เปลี่ยนมันต่อตาราง:

ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

แนวปฏิบัติที่ดีคือการเปลี่ยนที่ระดับตารางเนื่องจากจะเปลี่ยนเป็นคอลัมน์เช่นกัน การเปลี่ยนสำหรับคอลัมน์ที่เฉพาะเจาะจงสำหรับกรณีเฉพาะใด ๆ

การเปลี่ยนการเรียงสำหรับคอลัมน์ที่ระบุ:

ALTER TABLE <table_name> MODIFY <column_name> VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

15
อันนี้จริงตอบคำถามโดยตรง ฉันต้องการสิ่งนี้เนื่องจากการเปลี่ยนแปลงระดับตารางของฉันไม่ได้อัปเดตคอลัมน์ ฉันจะตรวจสอบว่าภายหลัง แต่นี่คือข้อมูลที่ช่วยให้ฉันผ่านช่วงเวลาที่ยากลำบาก ขอบคุณ
Parapluie

9
คำตอบที่ดีที่สุดสำหรับสิ่งนี้
jubi4dition

ใช่คุณต้องระบุประเภทคอลัมน์ นี่คือคำสั่งวิเศษที่จะได้รับทุกประเภท การใช้การแก้ไขหลายบรรทัดคุณสามารถสร้างคำสั่งเพื่ออัปเดตคอลัมน์ทั้งหมดในครั้งเดียวเริ่มต้นที่นี่:SELECT table_schema , table_name , column_name , COLLATION_NAME , COLUMN_TYPE FROM information_schema.columns WHERE collation_name != 'utf8_general_ci' AND table_schema not in ('information_schema','mysql', 'performance_schema','sys');
William Entriken

สำหรับคอลัมน์เดียวคุณสามารถทำได้: เปลี่ยนตาราง table_name CHANGE column_name VARCHAR (45) COLLATE utf8mb4_bin;
TomoMiha

68

คุณสามารถเรียกใช้สคริปต์ PHP

               <?php
                   $con = mysql_connect('localhost','user','password');
                   if(!$con) { echo "Cannot connect to the database ";die();}
                   mysql_select_db('dbname');
                   $result=mysql_query('show tables');
                   while($tables = mysql_fetch_array($result)) {
                            foreach ($tables as $key => $value) {
                             mysql_query("ALTER TABLE $value CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci");
                       }}
                   echo "The collation of your database has been successfully changed!";
                ?>

43

หากต้องการเปลี่ยนการเรียงหน้าสำหรับแต่ละตารางคุณสามารถใช้

ALTER TABLE mytable CONVERT TO CHARACTER SET utf8

ในการตั้งค่าการเรียงหน้าเริ่มต้นสำหรับฐานข้อมูลทั้งหมด

ALTER DATABASE  `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin

หรืออื่น ๆ,

ไปที่PhpMyAdmin-> Operations-> Collation

มีกล่องค้นหาที่คุณเลือกซึ่งมีการเปรียบเทียบทั้งหมดที่มีอยู่ เพื่อให้ที่นี่คุณสามารถเปลี่ยนการเปรียบเทียบของคุณ ดังนั้นที่นี่หลังจากตารางฐานข้อมูลจะติดตามการเปรียบเทียบนี้ในขณะที่คุณกำลังสร้างคอลัมน์ใหม่ ไม่จำเป็นต้องเลือกการเรียงหน้าในขณะที่สร้างคอลัมน์ใหม่


ขอบคุณมากนี่เป็นประโยชน์
JoZ3

15

แบบสอบถามต่อไปนี้จะสร้างแบบสอบถาม ALTER ที่เปลี่ยนการเรียงคอลัมน์ที่เหมาะสมทั้งหมดในตารางทั้งหมดเป็นประเภทที่แน่นอน (utf8_general_ci ในตัวอย่างของฉันด้านล่าง)

SELECT concat
        (
            'ALTER TABLE ', 
                t1.TABLE_SCHEMA, 
                '.', 
                t1.table_name, 
                ' MODIFY ', 
                t1.column_name, 
                ' ', 
                t1.data_type, 
                '(' , 
                    CHARACTER_MAXIMUM_LENGTH, 
                ')', 
                ' CHARACTER SET utf8 COLLATE utf8_general_ci;'
        )
from 
    information_schema.columns t1
where 
    t1.TABLE_SCHEMA like 'you_db_name_goes_here' AND
    t1.COLLATION_NAME IS NOT NULL AND
    t1.COLLATION_NAME NOT IN ('utf8_general_ci');

+1 ฉันชอบคำตอบนี้มากที่สุด ไม่ใช่ทุกคนที่มี PHP อย่างน่าอัศจรรย์ การใช้งานบางส่วนใช้ภาษาอื่นกับ MySQL สิ่งนี้ง่ายต่อการเรียกใช้ใน MySQL Workbench คัดลอกแถวและวาง ฉันเพิ่งทำขั้นตอนพิเศษเพื่อเรียกใช้ข้างต้นinformation_schema.tablesและรหัสใน concatALTER TABLE 'schema'.'table' CHARACTER SET = utf8mb4 , COLLATE = utf8mb4_bin ;
Pierre

1
ข้อผิดพลาดนี้เกิดขึ้นกับประเภทคอลัมน์ข้อความ (ขนาดกลาง / ยาว) ซึ่งจะต้องล้างข้อมูลด้วยตนเอง
stiebrs

11

หากคุณรัน phpMyAdmin >> เลือกฐานข้อมูล >> เลือกตาราง >> ไปที่แท็บ "ปฏิบัติการ" >> ในส่วน "ตัวเลือกตาราง" >> คุณสามารถเลือก Collation จากรายการแบบหล่นลง >> และเมื่อคุณกด {Go} ที่ ด้านบนของหน้าจอคุณจะเห็นข้อความ:

ดำเนินการค้นหา SQL ของคุณสำเร็จแล้ว

และสคริปต์

ALTER TABLE `tableName` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci 

แต่จะไม่เปลี่ยนการจัดเรียงของคอลัมน์ที่มีอยู่ ในการทำเช่นนั้นคุณสามารถใช้สคริปต์นี้ (อันนี้ก็มาจาก phpMyAdmin)

ALTER TABLE  `tableName` CHANGE  `Name`  `Name` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL


5

เพียงเรียกใช้ SQL นี้เพื่อแปลงตารางฐานข้อมูลทั้งหมดในครั้งเดียว เปลี่ยน COLLATION และ databaseName ของคุณเป็นสิ่งที่คุณต้องการ

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

4

คุณสามารถเปลี่ยน CHARSET และ COLLATION ของตารางทั้งหมดของคุณผ่านสคริปต์ PHP ดังต่อไปนี้ ฉันชอบคำตอบของ hkasera แต่ปัญหาของมันคือแบบสอบถามทำงานสองครั้งในแต่ละตาราง รหัสนี้เกือบเหมือนกันยกเว้นการใช้ MySqli แทนที่จะเป็น mysql และป้องกันการสืบค้นซ้ำสองครั้ง ถ้าฉันสามารถลงคะแนนได้ฉันจะโหวตให้คำตอบของ hkasera

<?php
$conn1=new MySQLi("localhost","user","password","database");
if($conn1->connect_errno){
    echo mysqli_connect_error();
    exit;
}
$res=$conn1->query("show tables") or die($conn1->error);
while($tables=$res->fetch_array()){
    $conn1->query("ALTER TABLE $tables[0] CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci") or die($conn1->error);
}
echo "The collation of your database has been successfully changed!";

$res->free();
$conn1->close();

?>

นี้ทำงานได้อย่างสมบูรณ์แบบสำหรับผมหลังจากการอัพเกรด Zabbix 5. เพียงแค่จะบอกว่าผมเปลี่ยนรหัสตัวอักษรและการเปรียบเทียบCONVERT TO CHARACTER SET utf8 COLLATE utf8_binเช่นนี้
robe007

4

คุณสามารถเพิ่มรหัสนี้ลงในไฟล์สคริปต์ได้ง่ายๆ

//Database Connection
$host = 'localhost';
$db_name = 'your_database_name';
$db_user =  'your_database_user_name';
$db_pass = 'your_database_user_password';

$con = mysql_connect($host,$db_user,$db_pass);

if(!$con) { echo "Cannot connect to the database ";die();}

  mysql_select_db($db_name);

  $result=mysql_query('show tables');

  while($tables = mysql_fetch_array($result)) {
    foreach ($tables as $key => $value) {
    mysql_query("ALTER TABLE $value CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci");
  }
}

echo "The collation of your database has been successfully changed!";

4

ฉันประหลาดใจที่ได้เรียนรู้และดังนั้นฉันจึงต้องกลับมาที่นี่และรายงานว่าการเชื่อมต่อที่ยอดเยี่ยมและได้รับการดูแลเป็นอย่างดี / ปลอดภัยค้นหาและแทนที่สคริปต์ฐานข้อมูลมีตัวเลือกบางอย่างสำหรับการแปลงตารางเป็น utf8 / unicode และแม้แต่แปลงเป็น Innodb . เป็นสคริปต์ที่ใช้กันทั่วไปในการโยกย้ายเว็บไซต์ที่ขับเคลื่อนด้วยฐานข้อมูล (Wordpress, Drupal, Joomla, ฯลฯ ) จากโดเมนหนึ่งไปยังอีกโดเมนหนึ่ง

ปุ่มสคริปต์เชื่อมต่อระหว่างกัน


3

ฉันอ่านที่นี่ว่าคุณต้องแปลงแต่ละตารางด้วยตนเองมันไม่เป็นความจริง นี่คือวิธีแก้ปัญหาด้วยโพรซีเดอร์ที่เก็บไว้:

DELIMITER $$

DROP PROCEDURE IF EXISTS changeCollation$$

-- character_set parameter could be 'utf8'
-- or 'latin1' or any other valid character set
CREATE PROCEDURE changeCollation(IN character_set VARCHAR(255))
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_table_name varchar(255) DEFAULT "";
DECLARE v_message varchar(4000) DEFAULT "No records";

-- This will create a cursor that selects each table,
-- where the character set is not the one
-- that is defined in the parameter

DECLARE alter_cursor CURSOR FOR SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE()
AND COLLATION_NAME NOT LIKE CONCAT(character_set, '_%');

-- This handler will set the value v_finished to 1
-- if there are no more rows

DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;

OPEN alter_cursor;

-- Start a loop to fetch each rows from the cursor
get_table: LOOP

-- Fetch the table names one by one
FETCH alter_cursor INTO v_table_name;

-- If there is no more record, then we have to skip
-- the commands inside the loop
IF v_finished = 1 THEN
LEAVE get_table;
END IF;

IF v_table_name != '' THEN

IF v_message = 'No records' THEN
SET v_message = '';
END IF;

-- This technic makes the trick, it prepares a statement
-- that is based on the v_table_name parameter and it means
-- that this one is different by each iteration inside the loop

SET @s = CONCAT('ALTER TABLE ',v_table_name,
' CONVERT TO CHARACTER SET ', character_set);
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET v_message = CONCAT('The table ', v_table_name ,
' was changed to the default collation of ', character_set,
'.\n', v_message);

SET v_table_name = '';

END IF;
-- Close the loop and the cursor
END LOOP get_table;
CLOSE alter_cursor;

-- Returns information about the altered tables or 'No records'
SELECT v_message;

END $$

DELIMITER ;

หลังจากสร้างโพรซีเดอร์แล้วให้เรียกมันว่า:

CALL changeCollation('utf8');

สำหรับรายละเอียดเพิ่มเติมอ่านบล็อกนี้


2

หากคุณต้องการอัปเดตชุดอักขระเริ่มต้นบนสคีมา:

 ALTER SCHEMA MYSCHEMA DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;

1

ฉันใช้เชลล์สคริปต์ต่อไปนี้ ใช้ชื่อฐานข้อมูลเป็นพารามิเตอร์และแปลงตารางทั้งหมดเป็นชุดอักขระและการเปรียบเทียบอื่น (กำหนดโดยพารามิเตอร์อื่นหรือค่าเริ่มต้นที่กำหนดไว้ในสคริปต์)

#!/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
)

1

โซลูชันของฉันคือการรวมกันของ @Dzintars และ @Quassnoi Answer

SELECT CONCAT("ALTER TABLE ", TABLE_SCHEMA, '.', TABLE_NAME," CONVERT TO CHARACTER SET utf8mb4 ;") AS    ExecuteTheString
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="<your-database>"
AND TABLE_TYPE="BASE TABLE";

โดยการใช้CONVERT TOสิ่งนี้จะสร้างสคริปต์ซึ่งแปลงตารางทั้งหมดเป็นการ<your-database>เข้ารหัสที่คุณร้องขอ สิ่งนี้จะเปลี่ยนการเข้ารหัสของทุกคอลัมน์ด้วย !


1

ตัวแปรที่ดีกว่าในการสร้างสคริปต์ SQL ตามคำขอของ SQL มันจะไม่ทำลายค่าเริ่มต้น / โมฆะ

SELECT concat
    (
        'ALTER TABLE ', 
            t1.TABLE_SCHEMA, 
            '.', 
            t1.table_name, 
            ' MODIFY ', 
            t1.column_name, 
            ' ', 
            t1.column_type,
            ' CHARACTER SET utf8 COLLATE utf8_general_ci',
            if(t1.is_nullable='YES', ' NULL', ' NOT NULL'),
            if(t1.column_default is not null, concat(' DEFAULT \'', t1.column_default, '\''), ''),
            ';'
    )
from 
    information_schema.columns t1
where 
    t1.TABLE_SCHEMA like 'your_table_here' AND
    t1.COLLATION_NAME IS NOT NULL AND
    t1.COLLATION_NAME NOT IN ('utf8_general_ci');

0

วิธีที่รวดเร็ว - ส่งออกไปยังไฟล์ SQL ใช้การค้นหาและแทนที่เพื่อเปลี่ยนข้อความที่คุณต้องการเปลี่ยน สร้างฐานข้อมูลใหม่นำเข้าข้อมูลจากนั้นเปลี่ยนชื่อฐานข้อมูลเก่าและฐานข้อมูลใหม่เป็นชื่อเก่า


0

หากต้องการเปลี่ยนการเปรียบเทียบของฟิลด์ทั้งหมดในตารางทั้งหมดของฐานข้อมูลพร้อมกัน:

ฉันเพิ่งเพิ่มวนรอบอื่นสำหรับเขตข้อมูลภายในตารางไปยังโซลูชันผ่าน Php ก่อนหน้านี้ สิ่งนี้ช่วยได้ฟิลด์ทั้งหมดในตารางจะถูกแปลงด้วย

<?php
$con = mysql_connect('localhost','user','pw');
if(!$con) { echo "Cannot connect to the database ";die();}
mysql_select_db('database_name');
$result=mysql_query('show tables');
while($tables = mysql_fetch_array($result)) {

foreach ($tables as $key => $table) {                   // for each table

    $sql = "ALTER TABLE $table CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci";
    echo "\n".$sql;
    mysql_query($sql);

    $sql = "show fields in ".$table." where type like 'varchar%' or type like 'char%' or type='text' or type='mediumtext';";
    $rs2=mysql_query($sql);
    while( $rw2 = mysql_fetch_array($rs2) ){            // for each field in table

        $sql = "ALTER TABLE `".$table."` CHANGE `".$rw2['Field']."` `".$rw2['Field']."` ".$rw2['Type']." CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;";
        echo "\n".$sql;
        mysql_query($sql);

    } 


}
}
echo "The collation of your database has been successfully changed!";

?>}

-1

ฉันเพิ่งเขียนสคริปต์ทุบตีเพื่อค้นหาตารางทั้งหมดในฐานข้อมูลที่กำหนดและซ่อนไว้ (และคอลัมน์)

สคริปต์มีให้ที่นี่: https://github.com/Juddling/mysql-charset

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.