`
丁林.tb
  • 浏览: 799248 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

让MySQL支持欧元字符

阅读更多

本文说明一下MySQL中不支持欧元字符的原因及解决方法。

 

 

1、              问题描述

mysql中插入的字符串中若包含欧元字符(),会发现该字符及以后的字符串都变得“不可见”。实际上这里并非不可见,而是根本没有进入数据库中。简单描述步骤如下:

root@test 05:15:41>create table t(c char(32)) engine=innodb charset=gbk;

Query OK, 0 rows affected (0.01 sec)

 

root@test 05:16:29>insert into t values(concat('a', char(128), 'b'));

Query OK, 1 row affected, 1 warning (0.00 sec)

 

root@test 05:17:04>select * from t;

+------+

| c    |

+------+

| a    |

+------+

 

 

可以看到,我们试图插入三个字符(a, €, b) 但在查询中发现只有一个字符a.

Insert的一个warning内容为 Incorrect string value: '\x80b' for column 'c' at row 1

说明在插入0x80(€) 时出错,导致后面的字符也一起被丢弃.

 

2、              原因分析

我们知道,在mysql将语句中设置的值传给引擎时,需要先拷贝到一个临时结构中。但拷贝字符串只会以\0结束,0x80对于字符串拷贝过程应该是一个正常的字符。

 

拷贝函数

于是我们找到做值拷贝的过程, sql/sql_string.ccwell_formed_copy_nchars中,对应的两行代码如下

 

 

res= to_cs->cset->well_formed_len(to_cs, from, from + from_length, 

                                        nchars, &well_formed_error);

      memmove(to, from, res);

 

 

可以看到,拷贝内容时,先计算了可拷贝的长度,然后在用memmove. 调试发现,在我们上面的试验中,返回的res=1 因此memmove就只拷贝了一个字符(a).

 

 

计算长度

于是问题出在这个to_cs->cset->well_formed_len中。

由于MySQL要支持多种字符编码,因此定义了MY_CHARSET_HANDLER (include/m_ctype.h)中,这个结构体定义了各种编码下的特定函数接口。对应的实现实体在strings/ctyp-*.c中。

我们的例子中用到的是gbk,因此看strings/ctype-gbk.c 上述计算长度的函数,实际上调用的是本文件中的my_well_formed_len_gbk

 

 

 

static
size_t my_well_formed_len_gbk(CHARSET_INFO *cs __attribute__((unused)),
                              const char *b, const char *e,
                              size_t pos, int *error)
{ 
  const char *b0= b;
  const char *emb= e - 1; /* Last possible end of an MB character */

  *error= 0;
  while (pos-- && b < e)
  { 
    if ((uchar) b[0] <= 128)
    { 
      /* Single byte ascii character */
      b++;
    }
    else  if ((b < emb) && isgbkcode((uchar)*b, (uchar)b[1]))
    { 
      /* Double byte character */
      b+= 2;
    }
    else
    { 
      /* Wrong byte sequence */
      *error= 1;
      break;
    }
  }
  return (size_t) (b - b0);
}

   

第12行是对于英文字符的处理,第17行是对于中文字符的处理,其他的直接到第22行后判为error。我们看到,0x80就到了*error=1, 然后break

 

 

3、              修改和小结

实际上欧元字符也可以作为单字节处理, 将上面代码的第12行改为if ((uchar) b[0] <= 128) 重新编译后执行结果如下

mysql> insert into t values(concat('a', char(128), 'b'));

Query OK, 1 row affected (0.00 sec)

 

insert select hex(c) from t;

+--------+

| hex(c) |

+--------+

| 618062 |

+--------+

欧元字符在笔者客户端内显示不正常,但从hex(c)中看到三个字符已经正常存储在mysql中。 

其他字符编码也有此问题,都修改相应的string/ctype-*.c中的my_well_formed_len*即可。

分享到:
评论
3 楼 jorneyR 2010-11-16  
把表的编码设置成unicode,然后插入没有任何问题的,已经测试过可以正常插入。
2 楼 丁林.tb 2010-11-15  
murusu 写道
需要这么复杂吗?
将表设置为unicode存储不就完事了

是说utf8吗

可以试下 也有问题

而且在原有数据上改表编码需要重做数据


有别的方法也可以提出下

不过这个只是提供一种解决思路而已
1 楼 murusu 2010-11-15  
需要这么复杂吗?
将表设置为unicode存储不就完事了

相关推荐

    mysql 解析json字符串

    mysql解析Json字符串插件 安装方法 1、拷贝lib_mysqludf_json_parsing.dll到mysql目录C:\Program Files\MariaDB 5.5\lib\plugin下 2、在数据库中执行 DROP FUNCTION json_get; CREATE FUNCTION json_get RETURNS ...

    mysql分割字符串

    虽然MySQL的正则表达式支持相对较弱,但仍然可以用来进行复杂的字符串处理。`REGEXP_SUBSTR()`或`REGEXP_REPLACE()`等函数可以帮助我们实现更灵活的分割。例如,通过正则表达式匹配并提取特定模式的子串。 五、JSON...

    MYSQL修改字符集默认问题

    ### 一、理解MySQL字符集 在深入探讨修改字符集的方法之前,我们首先需要了解MySQL中的字符集概念。字符集是指一系列字符及其编码方式的集合。在MySQL中,常用的字符集有`latin1`、`utf8`等。其中: - **`latin1`*...

    mysql 计算字符串相似度

    ### MySQL 计算字符串相似度 #### 背景与需求 在许多应用场景中,我们需要对两个字符串进行相似度比较,比如搜索引擎中的关键词匹配、文本分析中的近义词识别等。MySQL 提供了多种方法来实现字符串相似度的计算,...

    mysql字符集转换

    ### MySQL字符集转换详解 #### 一、引言 在MySQL数据库管理中,字符集的正确设置至关重要。它直接影响到数据的存储与检索效果,尤其是对于包含多种语言文本的应用场景而言。本文将围绕“MySQL字符集转换”这一主题...

    mysql字符集查看以及修改

    MySQL 字符集查看和修改 MySQL 字符集是 MySQL 数据库中最重要的配置之一,它影响着数据库的字符存储和比较方式。本文将介绍如何查看和修改 MySQL 字符集。 查看 MySQL 字符集 要查看 MySQL 字符集,可以使用 ...

    设置mysql字符集

    ### MySQL字符集的基本概念 字符集(Character Set)定义了数据在存储和处理时所采用的编码标准,而校对集(Collation)则规定了字符集下的排序规则和比较方式。在MySQL中,主要涉及以下几个关键变量: - `...

    mysql数据库互相转换及同步工具-MySQL_MySQL字符集互转

    本文将详细探讨“MySQL_MySQL字符集互转”这一主题,以及如何利用工具如"MSSQL2MySQLSync"进行数据库之间的转换与同步。 MySQL是一种广泛使用的开源关系型数据库管理系统,其支持多种字符集,包括UTF-8、GBK等。...

    MySql字符串相似匹配

    亲测可用,mysql字符串相似度匹配函数。下载后直接在mysql中可以测试运行。

    PB通过连接字符串连接MySQL

    标题中的“PB通过连接字符串连接MySQL”指的是使用PowerBuilder(PB)这个开发工具,通过特定的连接字符串来与MySQL数据库建立连接。PowerBuilder是Sybase公司(现为SAP的一部分)开发的一种可视化、面向对象的编程...

    查看mysql字符集MySQL 乱码的根源是的 MySQL 字符

    查看mysql字符集MySQL 乱码的根源是的 MySQL 字符

    Mysql 批量修改字符集

    MySQL 批量修改SCHEMA下所有数据表的编码及字符集

    mysql将字符串分割成多列值

    利用mysql中提供的所有函数,组成的一个存储过程。此存储过程主要是将传入的字符串分割为多个值,单个列。

    mysql字符集设置

    MySQL字符集设置是数据库管理中的一个重要环节,尤其是在处理多语言数据或者有特殊字符需求的应用中。字符集决定了数据库、表以及字段如何存储和显示字符,影响到数据的正确性及兼容性。以下将详细讲解MySQL字符集的...

    mysql 5.5 字符、性能设置标配

    1. 多语言支持:MySQL 5.5支持多种字符集,包括ASCII、UTF-8、GBK等,以满足不同语言环境的需求。UTF-8是最常用的一种,它可以存储世界上大部分语言的字符。 2. 全局字符集:全局字符集设置在my.cnf配置文件中,...

    MySql连接字符串总结

    本篇文章将详细介绍不同类型的MySQL连接字符串及其用法。 首先,我们来看MySQL Connector/ODBC的连接方式。ODBC(Open Database Connectivity)是一种通用数据库访问接口,它允许应用程序通过ODBC驱动程序连接到...

    linux修改mysql字符集

    Linux 修改 MySQL 字符集 在 Linux 系统中,MySQL 的字符集默认为 latin1,然而在某些情况下,我们需要修改 MySQL 的字符集以确保某些迁移的程序可以正常显示。在本文中,我们将介绍如何在 Linux 下修改 MySQL 的...

Global site tag (gtag.js) - Google Analytics