操作 'case' 的排序规则 (utf8_general_ci,COERCIBLE) 和 (latin1_swedish_ci,IMPLICIT) 的非法混合
Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'case'
我在 MySQL SERVER 5.5 和 MySQL SERVER 5.0 版本中使用两个 MySQL 服务器。我尝试在两个服务器中执行查询。这是我的查询:
DELIMITER $$
DROP PROCEDURE IF EXISTS `get_user_permissionlist`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `get_user_permissionlist`(
pUserId INT,
pApplicationId INT
)
BEGIN
DECLARE vDefaultManagerPermission VARCHAR(20);
SET vDefaultManagerPermission = (SELECT PermissionName FROM permission_level WHERE userid = pUserId);
IF vDefaultManagerPermission = 'Administrator'
THEN
SELECT PermissionId
,PermissionName
FROM ( SELECT pl.PermissionId
,pl.PermissionName
,CASE permissionname
WHEN 'administrator' THEN '1'
WHEN 'operator' THEN '2'
WHEN 'power user' THEN '3'
ELSE '4'
END AS rank
FROM permission_level pl
WHERE pl.ApplicationId = pApplicationId
) d
ORDER BY CASE WHEN rank <= 3 THEN rank
ELSE PermissionName
END;
END IF;
END $$
DELIMITER ;
我尝试使用以下查询执行过程。
CALL st_proc_get_user_permissionlist('5', '1')
当我在MySQL SERVER 5.0 中执行查询时,没有问题。但我在 MySQL SERVER 5.5 中尝试了同样的操作,它显示错误:
Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'case'
我不明白为什么它会抛出错误,而且两个服务器的字符集、排序规则都相同。
可能您开始时在两台服务器上使用了不同的默认 排序规则。我们从两个方向调试一下。
- 当 运行 查询时,从同一个连接执行
SHOW VARIABLES LIKE 'char%';
。这可能会检查查询中文字的 "character set"。
SHOW CREATE TABLE
每台服务器上的每个 table。这应该确定字段的字符集,例如 PermissionName
.
查看 bug 41627 是否适用,尽管它在 5.1.34 中是 'fixed'。
不涉及 VIEW
,对吗?
这真的很奇怪:
ORDER BY
CASE WHEN rank <= 3 THEN rank
ELSE PermissionName
END;
rank
设置为字符串1
、2
等,然后对比数字“3”,最后用PermissionName
排序,这好像成为字符串。我不知道这是否是导致麻烦的 CASE
,但我建议(为了我的理智)你不要混合数字和字符串。
你可以摆脱另一个案例:
WHERE PermissionName = CASE WHEN ApplicationId = 4
THEN 'administrator'
ELSE PermissionName END
重写为
WHERE ( PermissionName = 'administrator' OR ApplicationId != 4 )
编辑
由于数值组合比较奇怪,请尝试
ORDER BY CASE WHEN 0+rank <= 3 THEN CONCAT(_utf8 '', rank)
ELSE CONVERT(PermissionName USING utf8)
END;
我在 MySQL SERVER 5.5 和 MySQL SERVER 5.0 版本中使用两个 MySQL 服务器。我尝试在两个服务器中执行查询。这是我的查询:
DELIMITER $$
DROP PROCEDURE IF EXISTS `get_user_permissionlist`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `get_user_permissionlist`(
pUserId INT,
pApplicationId INT
)
BEGIN
DECLARE vDefaultManagerPermission VARCHAR(20);
SET vDefaultManagerPermission = (SELECT PermissionName FROM permission_level WHERE userid = pUserId);
IF vDefaultManagerPermission = 'Administrator'
THEN
SELECT PermissionId
,PermissionName
FROM ( SELECT pl.PermissionId
,pl.PermissionName
,CASE permissionname
WHEN 'administrator' THEN '1'
WHEN 'operator' THEN '2'
WHEN 'power user' THEN '3'
ELSE '4'
END AS rank
FROM permission_level pl
WHERE pl.ApplicationId = pApplicationId
) d
ORDER BY CASE WHEN rank <= 3 THEN rank
ELSE PermissionName
END;
END IF;
END $$
DELIMITER ;
我尝试使用以下查询执行过程。
CALL st_proc_get_user_permissionlist('5', '1')
当我在MySQL SERVER 5.0 中执行查询时,没有问题。但我在 MySQL SERVER 5.5 中尝试了同样的操作,它显示错误:
Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'case'
我不明白为什么它会抛出错误,而且两个服务器的字符集、排序规则都相同。
可能您开始时在两台服务器上使用了不同的默认 排序规则。我们从两个方向调试一下。
- 当 运行 查询时,从同一个连接执行
SHOW VARIABLES LIKE 'char%';
。这可能会检查查询中文字的 "character set"。 SHOW CREATE TABLE
每台服务器上的每个 table。这应该确定字段的字符集,例如PermissionName
.
查看 bug 41627 是否适用,尽管它在 5.1.34 中是 'fixed'。
不涉及 VIEW
,对吗?
这真的很奇怪:
ORDER BY
CASE WHEN rank <= 3 THEN rank
ELSE PermissionName
END;
rank
设置为字符串1
、2
等,然后对比数字“3”,最后用PermissionName
排序,这好像成为字符串。我不知道这是否是导致麻烦的 CASE
,但我建议(为了我的理智)你不要混合数字和字符串。
你可以摆脱另一个案例:
WHERE PermissionName = CASE WHEN ApplicationId = 4
THEN 'administrator'
ELSE PermissionName END
重写为
WHERE ( PermissionName = 'administrator' OR ApplicationId != 4 )
编辑
由于数值组合比较奇怪,请尝试
ORDER BY CASE WHEN 0+rank <= 3 THEN CONCAT(_utf8 '', rank)
ELSE CONVERT(PermissionName USING utf8)
END;