mysql 改变表table的字符集sql语句

正确的改变table字符集的语句是:
alter table xxx convert to character set utf8;
而不是想当然的:
alter table xxx default charset utf8;

字符集从GBK转成utf8,
会增大字段所占用的空间,有可能会改变字段的类型:
比如text有可能会自动变成medium text
但是varchar没有自动变成medium text.

下面看测试:

建一张GBK的表:
mysql> SHOW CREATE TABLE xxx;
CREATE TABLE `xxx` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(255) NOT NULL DEFAULT '',
  `body` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
 
用想当然的办法把它转成utf8:
mysql> ALTER TABLE xxx DEFAULT charset=utf8;
Query OK, 0 ROWS affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql>
mysql> SET names utf8;
Query OK, 0 ROWS affected (0.00 sec)
 
插入测试数据:
mysql> INSERT INTO xxx SET title='我爱北京天安门';
Query OK, 1 ROW affected (0.06 sec)
 
成功了。。。然后您就认为万事OK了?
 
mysql> INSERT INTO xxx SET title='㤇';    
Query OK, 1 ROW affected, 1 warning (0.03 sec)
Warning (Code 1366): Incorrect string VALUE: 'xE3xA4x87' FOR COLUMN 'title' at ROW 1
 
注意 title和body字段的CHARACTER SET 仍然为gbk
mysql> SHOW CREATE TABLE xxx;
| xxx   | CREATE TABLE `xxx` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(255) CHARACTER SET gbk NOT NULL DEFAULT '',
  `body` text CHARACTER SET gbk,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 |
 
正确的做法:
 
mysql> DROP TABLE xxx;
Query OK, 0 ROWS affected (0.02 sec)
 
mysql> CREATE TABLE `xxx` (
    ->   `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    ->   `title` VARCHAR(255) NOT NULL DEFAULT '',
    ->   `body` text,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
Query OK, 0 ROWS affected (0.06 sec)
 
mysql> ALTER TABLE xxx CONVERT TO CHARACTER SET utf8;
Query OK, 0 ROWS affected (0.14 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> INSERT INTO xxx SET title='㤇';                       
Query OK, 1 ROW affected (0.04 sec)
 
mysql> SHOW CREATE TABLE xxx;
| xxx   | CREATE TABLE `xxx` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(255) NOT NULL DEFAULT '',
  `body` mediumtext,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
 
可是你注意到 body字段从text变成 mediumtext了吗?
 
text字段,最多存储65535字节,换成GBK的字符就是32767个字符,这32767个gbk字符转成utf8却要占用98301字节,已经超过text的存储能力,所以被自动转成了mediumtext。
 
下面测试VARCHAR的情况:
 
VARCHAR除了数据部分,还有1-2个字节用来保存数据的长度。如果只使用一个字节,那么长度上限为255(2^8-1),如果使用二个字节,长度上限为65535(2^16-1)。
所以VARCHAR最多存储65535字节,换成GBK字符为32767个:
mysql> DROP TABLE xxx;
Query OK, 0 ROWS affected (0.02 sec)
 
mysql>
mysql> CREATE TABLE `xxx` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `title` VARCHAR(32768) NOT NULL DEFAULT '',
   PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;
ERROR 1074 (42000): COLUMN LENGTH too big FOR COLUMN 'title' (MAX = 32767); USE BLOB OR TEXT instead
mysql>
mysql>

可是 32767也是不成的。。还有每行记录的总长度限制(不包括text和BLOB字段) 65535:

mysql> CREATE TABLE `xxx` (   `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,   `title` VARCHAR(32767) NOT NULL DEFAULT '',   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;    
ERROR 1118 (42000): ROW SIZE too LARGE. The maximum ROW SIZE FOR the used TABLE TYPE, NOT counting BLOBs, IS 65535. You have TO CHANGE SOME COLUMNS TO TEXT OR BLOBs
mysql> CREATE TABLE `xxx` (   `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,   `title` VARCHAR(32766) NOT NULL DEFAULT '',   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;
ERROR 1118 (42000): ROW SIZE too LARGE. The maximum ROW SIZE FOR the used TABLE TYPE, NOT counting BLOBs, IS 65535. You have TO CHANGE SOME COLUMNS TO TEXT OR BLOBs
mysql> CREATE TABLE `xxx` (   `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,   `title` VARCHAR(32765) NOT NULL DEFAULT '',   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;
ERROR 1118 (42000): ROW SIZE too LARGE. The maximum ROW SIZE FOR the used TABLE TYPE, NOT counting BLOBs, IS 65535. You have TO CHANGE SOME COLUMNS TO TEXT OR BLOBs
mysql> CREATE TABLE `xxx` (   `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,   `title` VARCHAR(32764) NOT NULL DEFAULT '',   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;
Query OK, 0 ROWS affected (0.06 sec)
 
32764 * 2 + 2 + 4 = 65534 最接近于65535了,
32765 * 2 + 2 + 4 = 65536 超过65535。
*2是因为gbk字符占用2字节。
+2是VARCHAR还需要额外2字节保存数据的长度。
+4是id字段INT UNSIGNED占了4字节。
合理吗?
 
转换字符集为utf8之后,VARCHAR(32764) 已经不足以保存 32764个utf8字符:
 
mysql> ALTER TABLE xxx CONVERT TO CHARACTER SET utf8;
ERROR 1074 (42000): COLUMN LENGTH too big FOR COLUMN 'title' (MAX = 21845); USE BLOB OR TEXT instead
 
21845 * 3 = 65535.

后面附一些关于mysql数据库字符集修改方法

MySQL:修改默认字符集,转换字符集(MySQL 5.X)
 
1. 修改 MySQL 数据库默认字符集(mysql database default character set)
 
alter database testdb default character set = gb2312;  -www.2cto.com-
 
2. 修改 MySQL 数据表默认字符集(mysql table default character set)
 
alter table ip_to_country default character set = gb2312;
 
注意:修改 MySQL 的默认字符集,不管是在数据库级别,还是数据表级别,对已经存储的字符数据无任何改变。只是新增的表或列,开始使用新的字符集。

时间: 2024-10-31 06:59:28

mysql 改变表table的字符集sql语句的相关文章

mysql 多表关联更新/删除sql语句

1.mysql 多表关联delete中使用别名,tblwenhq是真实的表名,a是tblwenhq的别名,b是另一个表名  代码如下 复制代码 DELETE  a FROM tblwenhq a,b where a.id=b.id 2.使用mysql进行delete from操作时,若子查询的 FROM 字句和更新/删除对象使用同一张表,会出现错误. DELETE FROM tab1 WHERE col1 = ( SELECT MAX( col1 ) FROM tab1 ); ERROR 109

MySql多表关联Update更新sql语句

对单表执行更新没有什么好说的,无非就是update table_name set col1 = xx,col2 = yy where col = zz,主要就是where条件的设置.有时候更新某个表可能会涉及到多张数据表,例如:  代码如下 复制代码 update table_1 set score = score + 5 where uid in (select uid from table_2 where sid = 10); 其实update也可以用到left join.inner joi

MySQL开启记录执行过的SQL语句方法

  这篇文章主要介绍了MySQL开启记录执行过的SQL语句方法,配置的方法很简单,本文直接给出配置示例,需要的朋友可以参考下 概述 很多时候,我们需要知道 MySQL 执行过哪些 SQL 语句,比如 MySQL 被注入后,需要知道造成什么伤害等等.只要有 SQL 语句的记录,就能知道情况并作出对策.服务器是可以开启 MySQL 的 SQL 语句记录功能,从而就能间接地检测到客户端程序的行为. 方法 开启方法很简单:编辑/etc/my.cnf文件,在[mysqld]节下面添加:log=/var/l

select-在C#的combobox中显示数据库中所有的表名,但是sql语句不知道怎么写

问题描述 在C#的combobox中显示数据库中所有的表名,但是sql语句不知道怎么写 List<string> tableNames = "Select( (string)x["Table_Name"] from dt where type=1 and flags=0)"; dt是连接数据库时设定的表名 解决方案 sql语句如下所示:SELECT NAME FROM SYSOBJECTS WHERE TYPE='U' 前提是提前设置好config配置文

MySQL存储过程中实现执行动态SQL语句的方法_Mysql

本文实例讲述了MySQL存储过程中实现执行动态SQL语句的方法.分享给大家供大家参考.具体实现方法如下: mysql> mysql> delimiter $$ mysql> mysql> CREATE PROCEDURE set_col_value -> (in_table VARCHAR(128), -> in_column VARCHAR(128), -> in_new_value VARCHAR(1000), -> in_where VARCHAR(4

MySQL中查询所有数据库占用磁盘空间大小和单个库中所有表的大小的sql语句_Mysql

查询所有数据库占用磁盘空间大小的SQL语句: 复制代码 代码如下: select TABLE_SCHEMA, concat(truncate(sum(data_length)/1024/1024,2),' MB') as data_size,concat(truncate(sum(index_length)/1024/1024,2),'MB') as index_sizefrom information_schema.tablesgroup by TABLE_SCHEMAorder by dat

Mysql中文乱码以及导出为sql语句和Excel问题解决方法[图文]_Mysql

一.导出数据. 先说明一下自己的环境:Mac OS X 10.8.3, MySQL Community Server 5.6.10, MySQL Workbench 5.2.47. 我想把本机数据库内的数据迁移到另一台机器上,于是使用Workbench中自带的import/export功能,其实就是调用mysqldump.不幸的是,出现了版本不一致的错误. 错误没治了,最终找到解决方案,可以指定mysql的mysqldump,路径为:/usr/local/mysql/bin/mysqldump,

查询mysql中执行效率低的sql语句的方法_Mysql

一些小技巧1. 如何查出效率低的语句?在MySQL下,在启动参数中设置 --log-slow-queries=[文件名],就可以在指定的日志文件中记录执行时间超过long_query_time(缺省为10秒)的SQL语句.你也可以在启动配置文件中修改long query的时间,如: 复制代码 代码如下:  # Set long query time to 8 seconds    long_query_time=8 2. 如何查询某表的索引?可使用SHOW INDEX语句,如: 复制代码 代码如

Mysql中文乱码以及导出为sql语句和Excel问题解决

这几天基于Heritrix写了一个爬虫,用到mysql,在导入导出数据时,遇到一些乱码问题,好不容易解决了,记录一下,以备查看. 一.导出数据. 先说明一下自己的环境:Mac OS X 10.8.3, MySQL Community Server 5.6.10, MySQL Workbench 5.2.47. 我想把本机数据库内的数据迁移到另一台机器上,于是使用Workbench中自带的import/export功能,其实就是调用mysqldump.不幸的是,出现了版本不一致的错误. 错误没治了