如何从MySQL查询中的字符串中提取数值?

时间:2009-06-10 21:02:37

标签: mysql string numbers

我有一个包含两列的表:price(int)和price_display(varchar)。

价格是实际的数字价格,例如“9990”

price_display是视觉表示,例如“9.99美元”或“9.99Fr”

我已经能够通过regexp确认两列匹配:

  

price_display不是正则表达式   格式(价格/ 1000,2)

但是在不匹配的情况下,我想从price_display列中提取值并将其设置到price列中,所有这些都在update语句的上下文中。我无法弄清楚如何。

感谢。

6 个答案:

答案 0 :(得分:33)

此函数只执行从字符串返回数字0-9的工作,无论您使用的是什么前缀或后缀,都可以很好地解决您的问题。

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#815

复制此处以供参考:

SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
  DECLARE i, len SMALLINT DEFAULT 1;
  DECLARE ret CHAR(32) DEFAULT '';
  DECLARE c CHAR(1);

  IF str IS NULL
  THEN 
    RETURN "";
  END IF;

  SET len = CHAR_LENGTH( str );
  REPEAT
    BEGIN
      SET c = MID( str, i, 1 );
      IF c BETWEEN '0' AND '9' THEN 
        SET ret=CONCAT(ret,c);
      END IF;
      SET i = i + 1;
    END;
  UNTIL i > len END REPEAT;
  RETURN ret;
END |
DELIMITER ;

SELECT digits('$10.00Fr'); 
#returns 1000

答案 1 :(得分:5)

一种方法是使用REPLACE()函数:

UPDATE my_table
SET    price = replace(replace(replace(price_display,'Fr',''),'$',''),'.','')
WHERE  price_display not regexp format(price/1000, 2);

这适用于您提供的示例数据:

'$9.99'
'9.99Fr'

在我的测试中,两者都导致了999。通过这样的更新,确保首先备份数据库并了解项目的格式非常重要。通过执行此查询,您可以看到所有“坏人”:

SELECT   DISTINCT price_display
FROM     my_table
WHERE    price_display not regexp format(price/1000, 2)
ORDER BY price_display;

答案 2 :(得分:4)

对我而言,这个领域就是诀窍:

CAST( price AS UNSIGNED ) //正整数

CAST( price AS SIGNED ) //对于负整数和正整数

IF(CAST(price AS UNSIGNED)=0,REVERSE(CAST(REVERSE(price) AS UNSIGNED)),CAST(price AS UNSIGNED)) //当价格以其他东西开始时修复,然后是数字

有关详细信息,请参阅:

https://dev.mysql.com/doc/refman/5.0/en/cast-functions.html

答案 3 :(得分:1)

我创建了一个过程来检测字符串中的第一个数字并返回它,如果不返回0。

    DROP FUNCTION IF EXISTS extractNumber;
    DELIMITER //
    CREATE FUNCTION extractNumber (string1 VARCHAR(255)) RETURNS INT(11) 
        BEGIN
        DECLARE position, result, longitude INT(11) DEFAULT 0;
        DECLARE string2 VARCHAR(255);
        SET longitude = LENGTH(string1);
        SET result = CONVERT(string1, SIGNED);
        IF result = 0 THEN
            IF string1 REGEXP('[0-9]') THEN
                SET position = 2;
                checkString:WHILE position <= longitude DO
                    SET string2 = SUBSTR(string1 FROM position);
                    IF CONVERT(string2, SIGNED) != 0 THEN
                        SET result = CONVERT(string2, SIGNED);
                        LEAVE checkString;
                    END IF;
                    SET position = position + 1;
                END WHILE;
           END IF;
        END IF;
        RETURN result;
    END //
    DELIMITER ;

答案 4 :(得分:1)

从字符串中返回最后一个数字:

CREATE FUNCTION getLastNumber(str VARCHAR(255)) RETURNS INT(11)
DELIMETER //
BEGIN
    DECLARE last_number, str_length, position INT(11) DEFAULT 0;
    DECLARE temp_char VARCHAR(1);
    DECLARE temp_char_before VARCHAR(1);


IF str IS NULL THEN
    RETURN -1;
END IF;

SET str_length = LENGTH(str);

WHILE position <= str_length DO
    SET temp_char = MID(str, position, 1);

    IF position > 0 THEN
        SET temp_char_before = MID(str, position - 1, 1);
    END IF;

    IF temp_char BETWEEN '0' AND '9' THEN
        SET last_number = last_number * 10 + temp_char;
    END IF;
    IF (temp_char_before NOT BETWEEN '0' AND '9') AND 
           (temp_char BETWEEN '0' AND '9') THEN                 
        SET last_number = temp_char;
    END IF;

    SET position = position + 1;
END WHILE;

RETURN last_number;
END//
DELIMETER;

然后调用此函数:

选择getLastNumber(“ssss111www222w”); 打印222

选择getLastNumber(“ssss111www222www3332”); 打印3332

答案 5 :(得分:0)

这是一个“编码恐怖”,关系数据库模式应该 NOT 这样编写!

您必须编写复杂且不必要的代码来验证数据。

尝试这样的事情:

SELECT CONCAT('$',(price/1000)) AS Price FROM ...

此外,您可以使用floatdoublereal代替整数。

如果您需要存储货币数据,可以考虑添加货币字段或使用系统区域设置功能以正确的格式显示它。