从不规则格式的字符串中间返回数字

时间:2012-08-23 14:42:13

标签: mysql regex string substring

我在MySQL数据库中有一个字段,其中包含所购产品的商品说明。其中一些是简单的英文描述,其他是部分编号,其他仍然是部分编号,后面是描述。我已经使用replace()从字符串中删除了所有空格和短划线。

  

数据如下所示:

1938420985390asdfih
1234812934810dflkasd
asdfasldkjfaasdfjasd
asd;flkjaklsdf
adfsdf1234073927357sdapjfas
1/4sdikhsd 
  

我想回来:

1938420985390
1234812934810
(null)
(null)
1234073927357
(null)

我真正需要的是编写一个SQL,它将返回13位数的部件号,而不是额外的字母/字符。我希望它也会返回实际数字,而不是匹配/不匹配的1或0。

我尝试使用REGEXP函数(有人建议regexp ('\d{13}')regexp ('\p{13}')但这些不起作用。[这些返回0或1,而不是匹配的字符串部分。]任何建议?

谢谢!

5 个答案:

答案 0 :(得分:1)

这在MySQL中是一项非常重要的任务,没有用于返回正则表达式匹配的内置函数。但是因为你正在寻找13个数字,你可以做这样的事情(显然将它扩展到你需要检查的位置数量......

-- setup test
CREATE TABLE t (foo VARCHAR(30));
INSERT INTO t VALUES 
('1938420985390asdfih')
,('1234812934810dflkasd')
,('asdfasldkjfaasdfjasd')
,('asd;flkjaklsdf')
,('adfsdf1234073927357sdapjfas')
,('1/4sdikhsd')


SELECT CASE
       WHEN SUBSTR(foo,1,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,1,13)
       WHEN SUBSTR(foo,2,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,2,13)
       WHEN SUBSTR(foo,3,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,3,13)
       WHEN SUBSTR(foo,4,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,4,13)
       WHEN SUBSTR(foo,5,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,5,13)
       WHEN SUBSTR(foo,6,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,6,13)
       WHEN SUBSTR(foo,7,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,7,13)
       WHEN SUBSTR(foo,8,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,8,13)
       WHEN SUBSTR(foo,9,13) REGEXP '^[0-9]{13}$' THEN SUBSTR(foo,9,13)
       END AS digits
  FROM t

-------------------
1938420985390
1234812934810
(NULL)
(NULL)
1234073927357
(NULL) 

不,它不漂亮。但是你应该能够扩展它以有效地“扫描”一个合理长度的字符串。

注意:正则表达式检查整个13个字符的子字符串是否包含13个字符,每个字符都是十进制数字(0到9)。

答案 1 :(得分:0)

在MySQL中可能尚不支持获取匹配的值,如此处所述 - MySQL Regular Expressions with The REGEXP Operator。但是,如链接中所述,您可以使用第三方库,如下所示:UDF Repository for MySQL,它允许您使用PREG_CAPTURE捕获匹配项。

有关更多信息,此StackOverflow link似乎已处理此问题。

答案 2 :(得分:0)

如果每个条目只包含一个数字代码实例,那么这个代码可以工作:

SELECT CASE WHEN LENGTH(firstNumber(foo)) > 3 THEN firstNumber(foo) ELSE '' END AS result
FROM t

值得一提的两点:

  1. 数字长度必须至少为某个长度,比方说3个数字,这样我们就可以避免第6行1 / 4sdikhsd'中的1结果;
  2. 修改函数firstNumber以返回文本,但它实际上是相同的:

    DELIMITER //
    CREATE FUNCTION firstNumber(s TEXT)
        RETURNS TEXT
        COMMENT 'Returns the first integer found in a string'
    DETERMINISTIC
    BEGIN
    
    DECLARE token TEXT DEFAULT '';
    DECLARE len INTEGER DEFAULT 0;
    DECLARE ind INTEGER DEFAULT 0;
    DECLARE thisChar CHAR(1) DEFAULT ' ';
    
    SET len = CHAR_LENGTH(s);
    SET ind = 1;
    WHILE ind <= len DO
        SET thisChar = SUBSTRING(s, ind, 1);
        IF (ORD(thisChar) >= 48 AND ORD(thisChar) <= 57) THEN
            SET token = CONCAT(token, thisChar);
        ELSEIF token <> '' THEN
            SET ind = len + 1;
        END IF;
        SET ind = ind + 1;
    END WHILE;
    
    IF token = '' THEN
        RETURN '';
    END IF;
    
    RETURN token;
    
    END //    DELIMITER ;
    

答案 3 :(得分:0)

您要寻找的功能是REGEXP_SUBSTR()

SELECT REGEXP_SUBSTR(`dirty_value`,'[0-9]+') AS `clean_value` FROM `the_table`;

注意:我对其进行了测试并可以工作;我正在使用MySQL Server v8.0(不确定它是否在以前的版本中可用)。

祝你好运!

答案 4 :(得分:-1)

您可以使用linux中的mysql命令轻松地执行此操作,而不是grep

grep [0-9] foo.txt

然后创建表并将其加载到mysql中。