如何改变数据库,表,列的排序规则?

数据库现在是latin1_general_ci,我想把排序规则改为utf8mb4_general_ci

在PhpMyAdmin中是否有任何设置来更改数据库,表,列的排序规则?而不是一个一个地改变?

345503 次浏览

你需要单独转换每个表:

ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4

(这也会转换列),或者用latin1导出数据库,用utf8mb4导入数据库。

您可以在以下级别设置默认排序规则:

http://dev.mysql.com/doc/refman/5.0/en/charset-syntax.html

< p > 1)客户机 2)服务器默认 3)数据库默认 4)表默认 5)列< / p >

你可以运行一个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!";
?>

要更改表的排序规则,您可以使用,

ALTER TABLE mytable CONVERT TO CHARACTER SET utf8

若要为整个数据库设置默认排序规则,请执行以下操作

ALTER DATABASE  `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin

否则,

Goto PhpMyAdmin - >操作- >排序。

在这里,您可以找到包含所有现有排序规则的选择框。这样你就可以改变排序规则。在创建新列时,数据库表将遵循这个排序规则。创建新列时不需要选择排序规则。

您可以通过PHP脚本更改所有表的CHARSET和COLLATION,如下所示。我喜欢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();


?>

我在这里读到,你需要手动转换每个表,这是不正确的。下面是一个如何使用存储过程的解决方案:

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');

有关更多详细信息,请阅读博客

如果你运行phpMyAdmin >>选择数据库>>选择表>>到“操作”选项卡>>在“表选项”部分>>,你可以选择排序从下拉列表>>,一旦你按{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

快速方法-导出到SQL文件,使用搜索和替换来更改您需要更改的文本。创建新数据库,导入数据,然后将旧数据库和新数据库重命名为旧名称。

下面的查询将生成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');

您可以简单地将此代码添加到脚本文件

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

我在这里贡献,正如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;

我很惊讶地发现,所以我不得不回到这里报告,优秀和维护良好的Interconnect/it SAFE SEARCH and REPLACE ON DATABASE脚本有一些选项可以将表转换为utf8 / unicode,甚至转换为innodb。它是一个脚本,通常用于将数据库驱动的网站(Wordpress, Drupal, Joomla等)从一个域迁移到另一个域。

interconnect script buttons

如果你想更新架构的默认字符集:

 ALTER SCHEMA MYSCHEMA DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;

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

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

只需运行这个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";

我的解决方案是@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>的所有表转换为您所要求的编码。这也改变了每一列!

我刚刚编写了一个bash脚本来查找给定数据库中的所有表并隐藏它们(及其列)。

脚本可在这里获得:https://github.com/Juddling/mysql-charset

更好的变种生成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');

修改数据库中所有表中所有字段的排序规则。

我只是通过前面提到的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!";


?>}

注意,在改变数据库的字符集/表/列,实际上你可能需要将现有的数据(例如,如果你看到类似“U…Ø·U”UˆØ¨ØªUˆØ±UŠØ¯Ø¬U")是这样的:

update country set name = convert(cast(convert(name using latin1) as binary) using utf8), cn_flag = convert(cast(convert(cn_flag using latin1) as binary) using utf8), and so on..
而对于转换数据库,表和字段,我建议答案从这个线程,这将产生一个大的查询集,你只会复制粘贴,在这里我还没有找到一个自动的解决方案。 还要注意的是,如果你将同一个字段转换两次,你将得到不可恢复的问号:"??如果在转换字段/表之前转换数据,也会得到这个问号

生成查询来更新每个表和每个表的列。 我以前在我的一些项目中使用过这种方法,并且能够解决我的大部分COLLATION问题。(特别是在join上)

要使用,只需将结果导出为带分隔符的文本(可能是新行'\n')

每个表

SELECT CONCAT('ALTER TABLE `', TABLE_NAME,
'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
AS 'USE `DATABASE_NAME`;'
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_SCHEMA = 'DATABASE_NAME'
AND TABLE_TYPE LIKE 'BASE TABLE'

每一列

SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` MODIFY COLUMN `', COLUMN_NAME,'` ',
DATA_TYPE, IF(CHARACTER_MAXIMUM_LENGTH IS NULL
OR DATA_TYPE LIKE 'longtext', '', CONCAT('(', CHARACTER_MAXIMUM_LENGTH,
')')
), ' COLLATE utf8mb4_unicode_ci;') AS 'USE `DATABASE_NAME`;'
FROM   INFORMATION_SCHEMA.COLUMNS
WHERE  TABLE_SCHEMA = 'DATABASE_NAME'
AND (SELECT INFORMATION_SCHEMA.TABLES.TABLE_TYPE
FROM   INFORMATION_SCHEMA.TABLES
WHERE  INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA =
INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA
AND INFORMATION_SCHEMA.TABLES.TABLE_NAME =
INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
LIMIT  1) LIKE 'BASE TABLE'
AND DATA_TYPE IN ( 'char', 'varchar' ) /* include other types if necessary */