"latin1_german1_ci" 排序规则来自哪里?

Where is "latin1_german1_ci" collation coming from?

当 Java/Spring/Hibernate 应用程序尝试针对 mysql 数据库执行准备好的语句时,我收到以下错误消息:

Caused by: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin1_german1_ci,COERCIBLE) for operation '='

生成此语句的 select 语句(如 tomcat 日志中所示)是:

SELECT s.* FROM score_items s where  
s.s_score_id_l=299   and 
(s.p_is_plu_b = 'F')  and 
isTestProduct(s.p_upc_st) = 'N'  and 
v_is_complete_b='T'  
order by s.nc_name_st, s.p_upc_st

show table status 命令的 table 排序规则是:

 utf8_general_ci 

所有 char、varchar 和文本字段的排序规则是“utf8_general_ci”。 bigint、int 和 datetime 字段为 null。

数据库排序规则为 latin1_swedish_ci,如命令所示:

show variables like "collation_database";

编辑:我能够使用 Eclipse/STS 和 Tomcat 6 实例从我的本地机器成功地 运行 这个。本地进程正在从与生成错误的生产服务器上的进程相同的数据库中读取。发生错误的服务器是Tomcat 7. 实例是亚马逊Linux服务器。

编辑 2:当我从我们的 QA 环境 运行 报告时,我也能够成功地 运行 报告,JDBC 中的语句 server.xml 重置为指向生产数据库。 QA 本质上是生产环境的镜像,一些开发工作正在进行。我还应该注意到我上个月看到了一个类似的错误,但是当我重新运行 报告时它就消失了。最后,我不确定为什么它会有所作为,但被查询的 table 是巨大的,有超过 700 万行,每行可能有 100 个字段。

编辑 3:根据 Shadow 的评论,我发现在测试函数中指定了字符集 "latin1"。我已将其更改为 utf8,希望这能解决问题。

如何找出哪个字段是“latin1_german1_ci”?

当 table 和字段为“utf8_general_ci 或空值时,为什么使用“latin1_swedish_ci”进行比较?

问题是否与函数字符集有关,如果是,我如何确定它使用的是哪个字符 set/collation?

如何缩小 field/function 导致问题的范围?

这与 java 或休眠无关,这完全取决于 mysql,也许与连接字符串有关。

在mysql中可以定义多级字符集和排序规则,这会导致很多问题:

  • 服务器
  • 数据库
  • table
  • 连接

有关 character sets and collations 的详细信息,请参阅 mysql 文档。

总结一下:当且仅当您在较低级别未指定字符集或排序规则时,较高级别的默认值才会生效。因此,列级别定义会覆盖 table 级别定义。 show table status 命令显示 table 级别默认值,但这些可能已在列级别被覆盖。 show full columnsshow create table 命令将向您显示任何给定字段使用的真实字符集和排序规则。

连接级字符集/排序规则定义使情况更加复杂,因为 sql 语句中使用的字符串常量将使用连接字符集/排序规则,除非它们有显式声明。

但是,mysql 使用强制值来避免使用各种字符集和表达式引起的大多数问题,如 character sets / collations used in expressions 关于 character sets / collations used in expressions 的文档中所述。

从您提到的查询在从另一台计算机执行时有效表明问题与连接字符集/排序规则有关。我认为它将围绕 isTestProduct() 调用。

真正确定哪个条件导致问题的唯一方法是一个一个地消除条件,当错误消失时,最后消除的条件就是罪魁祸首。但是定义与字段中使用的内容一致的适当连接字符集和排序规则也会有所帮助。