MySQL CHAR变量类型在例程中不识别SPACE字符

时间:2018-04-30 02:17:15

标签: mysql

有人可以告诉我为什么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;  

1 个答案:

答案 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

根据documentation

  

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

的sql_mode的解决方案

而不是这样做:

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欺骗行为并为您提供预期结果。