16

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

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

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

我已经能够通过正则表达式确认两列匹配:

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

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

谢谢。

4

6 回答 6

37

这个函数只返回字符串中的数字 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
于 2009-06-13T23:46:54.603 回答
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;
于 2009-06-10T21:24:04.160 回答
5

对我来说,CASTING 字段起到了作用:

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

于 2015-04-06T19:46:17.437 回答
1

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

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

尝试这样的事情:

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

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

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

于 2009-06-10T21:20:11.157 回答
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 ;
于 2013-08-20T17:27:18.003 回答
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

于 2016-10-23T17:43:39.527 回答