【问题标题】:Where is "latin1_german1_ci" collation coming from?“latin1_german1_ci”排序规则来自哪里?
【发布时间】:2016-09-23 18:46:18
【问题描述】:

当 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 命令的表排序规则是:

 utf8_general_ci 

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

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

show variables like "collation_database";

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

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

编辑 3:基于 Shadow 的 cmets,我发现在测试函数中指定了字符集“latin1”。我已将其更改为 utf8 并希望这可以解决问题。

我如何知道哪个字段是“latin1_german1_ci”?

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

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

如何缩小导致问题的字段/功能?

【问题讨论】:

    标签: java mysql hibernate utf-8 collation


    【解决方案1】:

    这与java或hibernate无关,这纯粹是mysql,也许是连接字符串。

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

    • 服务器
    • 数据库
    • 表格
    • 连接

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

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

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

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

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

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

    【讨论】:

    • 谢谢,这是非常好的信息。我还在努力。非常奇怪的是,当指向 prod db 时,它既可以在我的机器上工作,也可以在 QA 环境中工作(请参阅上面的第二次编辑)。
    • 这就是为什么我相信问题出在连接排序规则上。您可以在连接字符串中指定它。
    • 我终于放弃了ghost,只是重新启动了应用程序,它工作了。我不知道为什么。谢谢!
    • "当且仅当在较低级别您不指定字符集或排序规则时,更高级别的默认值才会生效"——这并不完全正确:它们构成了 defaults 如果没有给出显式值,则在 创建时 使用,而此语句听起来好像它们是运行时的后备值。也就是说,服务器设置在创建新数据库时提供默认值;数据库设置在创建新表时提供默认值;和表设置在创建新列时提供默认值。连接设置为文字提供了默认值。
    • 这很重要,因为如果创建一个数据库对象(未指定显式字符集或排序规则),然后更改提供其默认值的设置,它将保留先前存在的值创建时间——就好像它已在创建语句中明确给出。
    猜你喜欢
    • 2011-07-31
    • 2010-09-21
    • 2011-12-05
    • 1970-01-01
    • 2012-09-11
    • 2014-04-24
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多