在 MySQL 库中有个 mix 表,它有一个列叫作 v,该列存储了文本和纯数值的内容。部分数据如下:

v       
--------
123     
abc     
1d3     
0       
123.0   
0123    
0#123   
0$123

希望使用 SQL 获取到只包含了数值的行。

由于 MySQL 并没有像 SQL Server 那样提供了ISNUMERIC() 函数判断内容是否是数值,我们只能使用曲线救国的方式解决了。

如果不考虑浮点数,可以把文本中的数字全部去掉,再判断剩下的内容的长度是否为 0 ,长度为 0 就说明是数值,否则是文本。

SELECT 
  * 
FROM
  mix 
WHERE LENGTH(
    REPLACE(
      REPLACE(
        REPLACE(
          REPLACE(
            REPLACE(
              REPLACE(
                REPLACE(
                  REPLACE(
                    REPLACE(REPLACE(v, '0', ''), '1', ''),
                    '2',
                    ''
                  ),
                  '3',
                  ''
                ),
                4,
                ''
              ),
              5,
              ''
            ),
            6,
            ''
          ),
          7,
          ''
        ),
        8,
        ''
      ),
      9,
      ''
    )
  ) = 0 
  

v       
--------
123     
0       
0123

上面这个SQL看着挺吓人的,在 MySQL 里没有 translate() 函数,就只能用 replace() 将 0 - 9 的数字逐个替换掉。

好在 MySQL 中支持使用正则表达式,可以使用 REGEXP  做正则表达式匹配。

SELECT * FROM mix WHERE v REGEXP '^[0-9]+$';


v       
--------
123     
0       
0123

REGEXP  比 REPLACE 的写法简洁很多。

如果要考虑浮点数,我们还可以把正则表达式变得更丰富点。

SELECT * FROM mix WHERE v REGEXP '^[0-9]*[.]?[0-9]+$';


v       
--------
123     
0       
123.0   
0123

假如还要支持查到带有“+”或者“-”的数值,正则表达式也能够做到。

SELECT * FROM mix WHERE v REGEXP '^[-+]?[0-9]*[.]?[0-9]+$';