【问题标题】:How to change collation of database, table, column?如何更改数据库、表、列的排序规则?
【发布时间】:2010-11-20 14:46:45
【问题描述】:

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

PhpMyAdmin 中是否有任何设置可以更改数据库、表、列的排序规则?而不是一一改变?

【问题讨论】:

标签: mysql collation


【解决方案1】:

按照 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;

【讨论】:

  • 这个其实直接回答了这个问题。我需要这个,因为我的表级更改没有更新列。我稍后会调查;但这是让我度过难关的信息。谢谢。
  • 最好的答案。
  • 是的,您需要指定列类型。这是获取所有类型的魔术命令。使用多行编辑,您可以生成命令以从此处开始一次更新所有列: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');
  • 对于单个列,您可以简单地执行以下操作: ALTER TABLE table_name CHANGE column_name VARCHAR(45) COLLATE utf8mb4_bin;
【解决方案2】:

您需要单独转换每个表格:

ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 

(这也将转换列),或者使用latin1 导出数据库并使用utf8mb4 将其导入回来。

【讨论】:

  • 但我想更改列的排序规则。这只会更改表排序规则..
  • @rsensan: CONVERT 也会改变列的排序规则。
  • ALTER SCHEMA database 默认字符集 utf8 默认排序 utf8_general_ci ;
  • @stormwild:这不会影响现有表
  • 我的查询:ALTER TABLE MYTABLE CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; Please don't use utf8_general_ci anymore ;-)
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    ALTER TABLE mytable CONVERT TO CHARACTER SET utf8
    

    为整个数据库设置默认排序规则,

    ALTER DATABASE  `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin
    

    否则,

    转到 PhpMyAdmin->Operations->整理。

    在那里您可以找到包含所有现有排序规则的选择框。这样您就可以在此处更改排序规则。因此,在创建新列时,数据库表将遵循此排序规则。创建新列时无需选择排序规则。

    【讨论】:

    • 非常感谢,这很有帮助
    【解决方案5】:

    以下查询将生成 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 和 concat ALTER TABLE 'schema'.'table' CHARACTER SET = utf8mb4 , COLLATE = utf8mb4_bin ; 中的代码执行了上述额外步骤
    • 这个错误出现在(中/长)文本列类型上,必须手动清理
    • 您可以使用 SCHEMA() 函数,而不是 'you_db_name_goes_here'
    • 而您正在失去 NULLable 和 DEFAULT 选项。
    【解决方案6】:

    如果您运行 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
    

    【讨论】:

      【解决方案7】:

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

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

      1) 客户 2) 服务器默认 3) 数据库默认 4) 表默认 5) 栏目

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

          您可以通过 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();
          
          ?>
          

          【讨论】:

          • 升级到 Zabbix 5 后,这对我来说非常有效。只是说我更改了 CharsetCollat​​ion 如下:CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin .
          【解决方案10】:

          生成查询以更新每个表和每个表的列。 我以前在我的一些项目中使用过它,并且能够解决我的大部分 COLLATION 问题。 (尤其是在 JOINS 上)

          要使用,只需将结果导出到分隔文本(可能是新行'\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 */
          

          【讨论】:

          • 为我工作。如果这导致约束错误,您可以使用SET foreign_key_checks = 0;,只需在数据库更新后使用SET foreign_key_checks = 1; 将其重新打开。
          • 谢谢,这是一个非常有帮助的答案。
          【解决方案11】:

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

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

          【讨论】:

            【解决方案12】:

            我很惊讶地得知,所以我不得不回到这里报告,优秀且维护良好的互连/它安全搜索和替换数据库脚本有一些用于将表转换为 utf8 / unicode 的选项,甚至转换为innodb。这是一个脚本,通常用于将数据库驱动的网站(Wordpress、Drupal、Joomla 等)从一个域迁移到另一个域。

            【讨论】:

              【解决方案13】:

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

              【讨论】:

              • 仅更改表排序规则不适用于列。只有这个脚本对我的情况有帮助。
              【解决方案14】:

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

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

              更多详情请阅读blog

              【讨论】:

                【解决方案15】:

                我的解决方案是@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,这会生成一个脚本,它将&lt;your-database&gt; 的所有表转换为您请求的编码。这也改变了每一列的编码!

                【讨论】:

                • 这当然是最好的答案!我只是想自己粘贴它,但它已经在这里了!请注意,您似乎不需要添加“COLLATE utf8mb4_unicode_ci;”就像在某些答案中一样,它似乎是额外的!
                【解决方案16】:

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

                 ALTER SCHEMA MYSCHEMA DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;
                

                【讨论】:

                  【解决方案17】:

                  我使用了以下 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
                  )
                  

                  【讨论】:

                    【解决方案18】:

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

                    【讨论】:

                      【解决方案19】:

                      一次更改数据库所有表中所有字段的排序规则:

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

                      【讨论】:

                        【解决方案20】:

                        注意,在更改数据库/表/列的字符集后,您可能需要实际转换现有数据(例如,如果您看到类似“مطلوب توريد ج Ù") 类似这样的东西:

                        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..
                        

                        在转换数据库、表和字段时,我建议 this 来自该线程的答案,这将生成大量查询,您只需在粘贴时复制这些查询,在这里我还找不到自动解决方案。 另请注意,如果您将同一字段转换两次,您将获得不可恢复的问号:“???”。如果在转换字段/表格之前转换数据,也会得到这个问号。

                        【讨论】:

                          【解决方案21】:

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

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

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2013-05-19
                            • 2011-04-08
                            • 2019-01-24
                            • 2013-08-05
                            • 1970-01-01
                            • 1970-01-01
                            • 2014-11-25
                            • 1970-01-01
                            相关资源
                            最近更新 更多