问题
我使用带有变量 @myVar 的本机函数 FIND_IN_SET 作为字符串列表,例如:
FIND_IN_SET(col, @myVar)
如果我从直接值设置 @myVar:
SET @myVAr = 'one,two,three';
... FIND_IN_SET(col, @myVar)
=> 效果很好
如果我从一个函数中设置@myVar,该函数从表的一列返回连接值:
SET @myVAr = '';
SELECT @myVAr := getStringOfValues();
... FIND_IN_SET(col, @myVar)
=> 我得到Erreur SQL (1267) : Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation 'find_in_set'
那么,我要摆脱这个错误吗?
请务必注意,我不想更改表格的排序规则。我希望我可以更改变量的排序规则,使其与我的列的排序规则相匹配,但我不能在初始化期间使用关键字“COLLATE”强制它:
SET @myVar= '' COLLATE utf8_unicode_ci;
=> 我得到Erreur SQL (1253) : COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'utf8mb4'
有用信息
我所有的表及其列都有排序规则 utf8_unicode_ci
SHOW VARIABLES LIKE '%char%'
character_set_client = utf8mb4
character_set_connection = utf8mb4
character_set_database = utf8
character_set_filesystem = 二进制
character_set_results = utf8mb4
character_set_server = latin1
character_set_system = utf8
SHOW VARIABLES LIKE 'coll%'
collation_connection = utf8mb4_general_ci
collation_database = utf8_general_ci
collation_server = latin1_swedish_ci
SHOW CREATE FUNCTION getStringOfValues
character_set_client = utf8mb4
collation_connection = utf8m4_general_ci
数据库排序规则 = utf8_general_ci
SQL 代码(匿名和简化版)
-- Function to return as a string the result from a SELECT in my_table_1
DELIMITER $$
CREATE FUNCTION getStringOfValues()
RETURNS TEXT
-- Variables to build the string of values
DECLARE curr_value VARCHAR(255) DEFAULT '';
DECLARE string_of_values TEXT DEFAULT '';
-- Variables to enter and exit the loop over values
DECLARE done INT DEFAULT 0;
DECLARE my_cursor CURSOR FOR SELECT col FROM my_table_1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cursor;
my_loop:LOOP
FETCH my_cursor INTO curr_value;
IF done THEN
LEAVE my_loop;
ELSE
SET string_of_values = CONCAT(curr_value, ',', string_of_values);
END IF;
END LOOP;
CLOSE my_cursor;
-- Remove the trailing comma and quote the string. Result in something like 'one,two,three'
RETURN QUOTE(TRIM(TRAILING ',' FROM string_of_values));
$$
DELIMITER ;
SET @myVAr = 'one,two,three';
-- The statement below will WORK
SELECT * FROM my_table_2 WHERE FIND_IN_SET(col, @myVAr);
SELECT @myVAr := getStringOfValues();
-- The statement below will NOT WORK as there is a 'Illegal mix of collations'
SELECT * FROM my_table_2 WHERE FIND_IN_SET(col, @myVAr);