我得到下面的错误时,试图做一个选择通过一个存储过程在MySQL。

操作'='的排序规则(latin1_general_cs,IMPLICIT)和(latin1_general_ci,IMPLICIT)的非法混合

你知道哪里出了问题吗?

该表的排序规则为latin1_general_ci, where子句中的列的排序规则为latin1_general_cs。


当前回答

MySQL真的不喜欢混合排序规则,除非它可以将它们强制到同一个排序规则(这在您的情况下显然是不可行的)。难道不能通过COLLATE子句强制使用相同的排序规则吗?(或更简单的二进制快捷方式,如果适用…)

其他回答

如果安装了phpMyAdmin,可以按照以下链接中给出的说明进行操作:https://mediatemple.net/community/products/dv/204403914/default-mysql-character-set-and-collation您必须将数据库的排序规则与所有表的排序规则以及表中的字段进行匹配,然后重新编译所有存储过程和函数。这样,一切就都能正常工作了。

我有一个类似的问题,试图使用FIND_IN_SET过程与字符串变量。

SET @my_var = 'string1,string2';
SELECT * from my_table WHERE FIND_IN_SET(column_name,@my_var);

并且正在接收错误

错误码:1267。排序规则的非法混合(utf8_unicode_ci,IMPLICIT) 和(utf8_general_ci,隐式)操作'find_in_set'

简短的回答:

不需要更改任何collation_YYYY变量,只需在变量声明旁边添加正确的排序规则,即。

SET @my_var = 'string1,string2' COLLATE utf8_unicode_ci;
SELECT * from my_table WHERE FIND_IN_SET(column_name,@my_var);

长一点的回答:

我首先检查了排序变量:

mysql> SHOW VARIABLES LIKE 'collation%';
    +----------------------+-----------------+
    | Variable_name        | Value           |
    +----------------------+-----------------+
    | collation_connection | utf8_general_ci |
    +----------------------+-----------------+
    | collation_database   | utf8_general_ci |
    +----------------------+-----------------+
    | collation_server     | utf8_general_ci |
    +----------------------+-----------------+

然后我查看了表格整理:

mysql> SHOW CREATE TABLE my_table;

CREATE TABLE `my_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `column_name` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=125 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

这意味着我的变量被配置为默认排序规则utf8_general_ci,而我的表被配置为utf8_unicode_ci。

通过在变量声明旁边添加COLLATE命令,变量排序规则与为表配置的排序规则相匹配。

在我的例子中,函数的默认返回类型是来自数据库的类型/排序规则(utf8mb4_general_ci),但数据库列是ascii。

WHERE ascii_col = md5(concat_ws(',', a,b,c))

权宜之计是

WHERE ascii_col = BINARY md5(concat_ws(',', a,b,c))

如果你遇到问题的列是“散列”,那么考虑以下…

如果“hash”是二进制字符串,你应该使用binary(…)数据类型。

如果“哈希”是一个十六进制字符串,你不需要utf8,应该避免这样做,因为字符检查等。例如,MySQL的MD5(…)会产生一个固定长度的32字节十六进制字符串。SHA1(…)给出一个40字节的十六进制字符串。这可以存储到CHAR(32)字符集ascii(或40的sha1)。

或者,更好的是,将UNHEX(MD5(…))存储为BINARY(16)。这样就把柱子的大小减少了一半。(然而,这确实使它不适合印刷。)SELECT十六进制(散列)…如果你想让它可读。

比较两个BINARY列没有排序规则问题。

解决方案,如果文字涉及。

我使用Pentaho数据集成,不需要指定sql语法。 使用非常简单的DB查找就会出现错误 "操作'='的排序规则(cp850_general_ci, coerble)和(latin1_swedish_ci, coerble)的非法混合"

生成的代码是 SELECT DATA_DATE AS latest DATA_DATE FROM hr_cc_normalised_data_date_v WHERE PSEUDO_KEY = ?"

长话短说,查找是一个视图,当我发布

mysql> show full columns from hr_cc_normalised_data_date_v;
+------------+------------+-------------------+------+-----+
| Field      | Type       | Collation         | Null | Key |
+------------+------------+-------------------+------+-----+
| PSEUDO_KEY | varchar(1) | cp850_general_ci  | NO   |     |
| DATA_DATE  | varchar(8) | latin1_general_cs | YES  |     |
+------------+------------+-------------------+------+-----+

这就解释了“cp850_general_ci”的来源。

视图是用'SELECT 'X',......'创建的 根据手册,这样的文字应该从服务器设置继承字符集和排序规则服务器设置被正确地定义为" latin1 "和" latin1_general_cs " 因为这显然没有发生,我强迫它在创建视图

CREATE OR REPLACE VIEW hr_cc_normalised_data_date_v AS
SELECT convert('X' using latin1) COLLATE latin1_general_cs        AS PSEUDO_KEY
    ,  DATA_DATE
FROM HR_COSTCENTRE_NORMALISED_mV
LIMIT 1;

现在它为两个列显示latin1_general_cs,错误已经消失。:)