有人可以告诉我为什么MySQL在分配给CHAR变量时无法识别SPACE字符吗?
下面的示例代码简单地将char中的输入char回送到变量中以进行演示。
当使用my_test(' 1 2')调用时,这是6个字符总输入,包含4个空格,结果只有' 12'两个人回来了。
如果我将ch的定义更改为CHAR(2),CHAR(4),CHAR(10)......结果相同。
如果我将ch的定义更改为VARCHAR(1),它会按照我的预期工作,返回所有6个原始字符。
对我来说,这似乎是MySQL处理CHAR的错误。使用CHAR(1)的相同代码(稍作语法更改)在Oracle和SQL Server上运行良好。
使用MySQL 5.7.21
/*
select my_test('1 2'); -- Total len = 6 (contains 4 spaces)
*/
DROP FUNCTION IF EXISTS my_test;
DELIMITER //
CREATE FUNCTION my_test( original VARCHAR(100) )
RETURNS VARCHAR(100)
DETERMINISTIC
BEGIN
DECLARE ch CHAR(1); -- Will only recognize SPACE if changed to VARCHAR!
DECLARE idx INT DEFAULT 1;
DECLARE len INT;
DECLARE result VARCHAR(100) DEFAULT '';
SET len = CHAR_LENGTH(original);
WHILE idx <= len DO
SET ch = SUBSTR(original, idx, 1);
SET result = CONCAT(result, ch);
SET idx = idx + 1;
END WHILE;
RETURN result;
END;
答案 0 :(得分:0)
通过确保在sql_mode设置为pad_char_to_full_length
的情况下创建函数,可以解决您看到的问题。
<强>解决方案强>
DROP FUNCTION IF EXISTS my_test;
SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
DELIMITER //
CREATE FUNCTION my_test( original VARCHAR(100) )
RETURNS VARCHAR(100)
DETERMINISTIC
BEGIN
DECLARE ch CHAR(1);
DECLARE idx INT DEFAULT 1;
DECLARE len INT;
DECLARE result VARCHAR(100) DEFAULT '';
SET len = CHAR_LENGTH(original);
WHILE idx <= len DO
SET ch = SUBSTR(original, idx, 1);
SET result = CONCAT(result, ch);
SET idx = idx + 1;
END WHILE;
RETURN result;
END//
delimiter ;
SET sql_mode = '';
<强>结果强>
select my_test('1 2');
+-----------------+
| my_test('1 2') |
+-----------------+
| 1 2 |
+-----------------+
<强>解释强>
如果你有CHAR(5)
并且存储了A
,那么MySQL将在内部将其存储为A
。但是,当您从CHAR(5)
中进行选择时,不会检索右边填充的空格,而是设置了pad_char_to_full_length
sql_mode。默认情况下,您的sql_mode可能没有pad_char_to_full_length
。
CHAR列的长度固定为您声明的长度 当你创建表时。长度可以是0到255之间的任何值。 存储CHAR值时,它们右边用空格填充 指定长度。检索CHAR值时,尾随空格为 删除除非启用PAD_CHAR_TO_FULL_LENGTH SQL模式。
因此,SET ch = SUBSTR(original, idx, 1);
在ch
中存储空格。但是,当从ch
MySQL中提取信息时,将从末尾截断空格,从而导致空字符串。
<强>的sql_mode 强>
您可以通过键入select @@sql_mode
来查看当前的sql_mode。另请参阅How can I see the specific value of the sql_mode?。
您可以在MySQL's doc中查看sql_mode的文档。
不使用pad_char_to_full_length
而不是这样做:
SET ch = SUBSTR(original, idx, 1);
SET result = CONCAT(result, ch);
请改为:
SET result = CONCAT(result, SUBSTR(original, idx, 1));
即使sql_mode没有CHAR
,此单行分配也会避免使用pad_char_to_full_length
欺骗行为并为您提供预期结果。