COLLATION对于与我的设置不对应的CHARACTER SET无效

时间:2015-03-05 08:49:49

标签: php mysql mysqli collation

我已经问过another question我的排序规则设置问题,这似乎被一些不需要的默认设置忽略/覆盖。要解决此问题,我想在返回" illegal mix of collations"的查询中使用COLLATE。错误。但是,当我尝试时,我得到" COLLATION无效"而错误。

有问题的查询(我还没有遇到其他查询的问题),这次参数COLLATE ?转换为逗号分隔数字字符串) :

SELECT k.url 
FROM kml k 
WHERE (
    SELECT GROUP_CONCAT(
        kat.kategorie ORDER BY kat.kategorie 
    )
    FROM kml_kategorie kat
    WHERE kat.kml = k.id
) = ? COLLATE utf8_czech_ci
LIMIT 1;

运行时,我收到以下错误:

COLLATION 'utf8_czech_ci' is not valid for CHARACTER SET 'binary'

当我在Adminer中运行show variables like "%character_set_%"时,我得到以下结果:

---------------------------------------  
| Variable_name            | Value    |  
---------------------------------------  
| character_set_client     | utf8     |  
| character_set_connection | utf8     |  
| character_set_database   | utf8     |  
| character_set_filesystem | binary   |  
| character_set_results    | utf8     |  
| character_set_server     | utf8     |  
| character_set_system     | utf8     |  
---------------------------------------

当我从php / mysqli调用命令时,唯一的区别是即使character_set_filesystem的值为utf8

好吧,也许在这种情况下,无论mysqli显示什么,都会使用数据库设置。但后来我尝试通过将COLLATE添加到聚合函数GROUP_CONCAT来解决任何强制性问题:

SELECT k.url 
FROM kml k 
WHERE (
    SELECT GROUP_CONCAT(
        kat.kategorie ORDER BY kat.kategorie COLLATE utf8_czech_ci 
    )
    FROM kml_kategorie kat
    WHERE kat.kml = k.id
) = ?
LIMIT 1;

现在错误如下:

COLLATION 'utf8_czech_ci' is not valid for CHARACTER SET 'latin1'

您可以看到charset变量值中没有latin1。在我修改character_set_server文件之前,它曾是my.cnf的值。它的相关部分现在看起来像这样:

## UTF 8 Settings
#init-connect=\'SET NAMES utf8\'
collation_server=utf8_czech_ci
character_set_server=utf8
character-set-filesystem=utf8
#skip-character-set-client-handshake
#character_sets-dir="C:/xampp/mysql/share/charsets"

错误消息中显示的字符集(并导致问题)来自何处?我对查询mysqli / php和adminer中的变量之间的差异感到困惑,并且完全被其他一些变量所困惑,这使得这个更加混乱。如何清理它并更改变量,以便至少这个COLLATE解决方法有效?

这基本上是my linked question的一个子问题,但又不同,值得分裂;结合的两个问题就像我的数据库变量一样混乱。但是,很可能其中一个解决方案也能解决另一个问题;在回答之后,你可以考虑通过你的第一个答案摘要+一个说明如何适用于问题中指定的问题来回答另一个问题。

编辑:我发现了a workaround这个特例。但是,我仍然没有找到为什么通过Adminer和Mysqli进行的查询返回不同的结果特别是为什么错误消息指向不包含在任何变量中的字符集

2 个答案:

答案 0 :(得分:1)

kat.kategorie的数据类型是什么?

GROUP_CONCAT( kat.kategorie
              ORDER BY CONVERT(kat.kategorie USING utf8) COLLATE utf8_czech_ci 
            )

您可能还需要拨打CAST(... AS CHAR)

将来不要混用CHARACTER SET。

GROUP_CONCAT以及涉及组合事物的其他几个函数在推断结果类型应该是什么时遇到问题。在某些情况下,它会调用并调用结果BINARY,这比你遇到的更糟糕。

我相信某个地方有一个拉丁语导致了你的特殊问题。挖掘Adminer。让我们看看SHOW CREATE TABLE kat。

答案 1 :(得分:0)

我做了另一个解决方法:我在数据库中创建了一个视图,以避免在mysqli参数化查询中调用GROUP_CONCAT。错误不再出现,但我仍然不认为它已完全解决,因为有些奇怪的事情我不明白(变量没有正确设置等)我不知道不希望他们再犯任何问题。

观点:

CREATE 
  ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` 
  SQL 
  SECURITY DEFINER 
VIEW `kml_kat_vw` AS SELECT 
  `kml_kategorie`.`kml` AS `_kml`,
  group_concat(
    `kml_kategorie`.`kategorie`
    ORDER BY `kml_kategorie`.`kategorie` ASC separator ','
  ) AS `_kategorie` 
FROM `kml_kategorie`
GROUP BY `kml_kategorie`.`kml`

新查询:

SELECT k.url
FROM kml k
JOIN kml_kat_vw kat ON kat._kml = k.id
WHERE kat._kategorie = ?;
相关问题