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

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

你知道哪里出了问题吗?

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


当前回答

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

其他回答

一个可能的解决方案是将整个数据库转换为UTF8(另见此问题)。

在我的例子中,函数的默认返回类型是来自数据库的类型/排序规则(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列没有排序规则问题。

博士TL;

更改一个(或两个)字符串的排序规则,使它们匹配,或者在表达式中添加COLLATE子句。


What is this "collation" stuff anyway? As documented under Character Sets and Collations in General: A character set is a set of symbols and encodings. A collation is a set of rules for comparing characters in a character set. Let's make the distinction clear with an example of an imaginary character set. Suppose that we have an alphabet with four letters: “A”, “B”, “a”, “b”. We give each letter a number: “A” = 0, “B” = 1, “a” = 2, “b” = 3. The letter “A” is a symbol, the number 0 is the encoding for “A”, and the combination of all four letters and their encodings is a character set. Suppose that we want to compare two string values, “A” and “B”. The simplest way to do this is to look at the encodings: 0 for “A” and 1 for “B”. Because 0 is less than 1, we say “A” is less than “B”. What we've just done is apply a collation to our character set. The collation is a set of rules (only one rule in this case): “compare the encodings.” We call this simplest of all possible collations a binary collation. But what if we want to say that the lowercase and uppercase letters are equivalent? Then we would have at least two rules: (1) treat the lowercase letters “a” and “b” as equivalent to “A” and “B”; (2) then compare the encodings. We call this a case-insensitive collation. It is a little more complex than a binary collation. In real life, most character sets have many characters: not just “A” and “B” but whole alphabets, sometimes multiple alphabets or eastern writing systems with thousands of characters, along with many special symbols and punctuation marks. Also in real life, most collations have many rules, not just for whether to distinguish lettercase, but also for whether to distinguish accents (an “accent” is a mark attached to a character as in German “Ö”), and for multiple-character mappings (such as the rule that “Ö” = “OE” in one of the two German collations). Further examples are given under Examples of the Effect of Collation. Okay, but how does MySQL decide which collation to use for a given expression? As documented under Collation of Expressions: In the great majority of statements, it is obvious what collation MySQL uses to resolve a comparison operation. For example, in the following cases, it should be clear that the collation is the collation of column charset_name: SELECT x FROM T ORDER BY x; SELECT x FROM T WHERE x = x; SELECT DISTINCT x FROM T; However, with multiple operands, there can be ambiguity. For example: SELECT x FROM T WHERE x = 'Y'; Should the comparison use the collation of the column x, or of the string literal 'Y'? Both x and 'Y' have collations, so which collation takes precedence? Standard SQL resolves such questions using what used to be called “coercibility” rules. [ deletia ] MySQL uses coercibility values with the following rules to resolve ambiguities: Use the collation with the lowest coercibility value. If both sides have the same coercibility, then: If both sides are Unicode, or both sides are not Unicode, it is an error. If one of the sides has a Unicode character set, and another side has a non-Unicode character set, the side with Unicode character set wins, and automatic character set conversion is applied to the non-Unicode side. For example, the following statement does not return an error: SELECT CONCAT(utf8_column, latin1_column) FROM t1; It returns a result that has a character set of utf8 and the same collation as utf8_column. Values of latin1_column are automatically converted to utf8 before concatenating. For an operation with operands from the same character set but that mix a _bin collation and a _ci or _cs collation, the _bin collation is used. This is similar to how operations that mix nonbinary and binary strings evaluate the operands as binary strings, except that it is for collations rather than data types. So what is an "illegal mix of collations"? An "illegal mix of collations" occurs when an expression compares two strings of different collations but of equal coercibility and the coercibility rules cannot help to resolve the conflict. It is the situation described under the third bullet-point in the above quotation. The particular error given in the question, Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '=', tells us that there was an equality comparison between two non-Unicode strings of equal coercibility. It furthermore tells us that the collations were not given explicitly in the statement but rather were implied from the strings' sources (such as column metadata). That's all very well, but how does one resolve such errors? As the manual extracts quoted above suggest, this problem can be resolved in a number of ways, of which two are sensible and to be recommended: Change the collation of one (or both) of the strings so that they match and there is no longer any ambiguity. How this can be done depends upon from where the string has come: Literal expressions take the collation specified in the collation_connection system variable; values from tables take the collation specified in their column metadata. Force one string to not be coercible. I omitted the following quote from the above: MySQL assigns coercibility values as follows: An explicit COLLATE clause has a coercibility of 0. (Not coercible at all.) The concatenation of two strings with different collations has a coercibility of 1. The collation of a column or a stored routine parameter or local variable has a coercibility of 2. A “system constant” (the string returned by functions such as USER() or VERSION()) has a coercibility of 3. The collation of a literal has a coercibility of 4. NULL or an expression that is derived from NULL has a coercibility of 5. Thus simply adding a COLLATE clause to one of the strings used in the comparison will force use of that collation. Whilst the others would be terribly bad practice if they were deployed merely to resolve this error: Force one (or both) of the strings to have some other coercibility value so that one takes precedence. Use of CONCAT() or CONCAT_WS() would result in a string with a coercibility of 1; and (if in a stored routine) use of parameters/local variables would result in strings with a coercibility of 2. Change the encodings of one (or both) of the strings so that one is Unicode and the other is not. This could be done via transcoding with CONVERT(expr USING transcoding_name); or via changing the underlying character set of the data (e.g. modifying the column, changing character_set_connection for literal values, or sending them from the client in a different encoding and changing character_set_client / adding a character set introducer). Note that changing encoding will lead to other problems if some desired characters cannot be encoded in the new character set. Change the encodings of one (or both) of the strings so that they are both the same and change one string to use the relevant _bin collation. Methods for changing encodings and collations have been detailed above. This approach would be of little use if one actually needs to apply more advanced collation rules than are offered by the _bin collation.

这段代码需要放在运行SQL查询/数据库查询

SQL查询窗口

ALTER TABLE `table_name` CHANGE `column_name` `column_name`   VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;

请用合适的名称替换table_name和column_name。