如何在SQLite中依据值类型(数值型与文本型)过滤列值?
在SQLite中按值的类型(数值/文本)过滤列值的正确方法
你提到的CAST函数失效问题确实很典型——SQLite的CAST对数值的判定规则非常宽松,只要字符串开头包含数字,它就会提取前面的数字部分转成数值,比如CAST('1a' AS NUMERIC)会得到1,根本没法区分纯数值和带非数字字符的文本。下面给你几个靠谱的解决方案:
方法一:用正则表达式(推荐,SQLite 3.33.0+支持)
从SQLite 3.33.0版本开始,官方支持了REGEXP运算符,我们可以用正则精准匹配纯数值(包括整数、浮点数、科学计数法格式):
匹配所有合法数值
SELECT * FROM your_table WHERE your_column REGEXP '^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$';
这个正则的逻辑是:
- 允许开头带正负号(可选)
- 支持三种数值格式:整数(如
123)、带小数的数(如123.45、123.)、小数点开头的小数(如.45) - 支持科学计数法(如
1.23e4、-5.6E-7)
只匹配整数
如果只需要过滤纯整数,把正则简化成:
SELECT * FROM your_table WHERE your_column REGEXP '^[-+]?\d+$';
方法二:类型转换后对比(兼容低版本SQLite)
如果你的SQLite版本比较旧,不支持REGEXP,可以利用“转成数值再转回文本,和原字符串对比”的思路:
SELECT * FROM your_table WHERE CAST(your_column AS TEXT) = CAST(CAST(your_column AS NUMERIC) AS TEXT);
原理很简单:
- 纯数值字符串(如
'123'、'123.45')转成NUMERIC再转回TEXT,结果和原字符串完全一致 - 带非数字字符的字符串(如
'1a'、'abc123')转成NUMERIC后会丢失非数字部分,转回TEXT后和原字符串不等,从而被过滤掉
⚠️ 注意:这个方法对'123.'或'.45'这类格式的数值也能识别,但如果你的场景里不允许这种格式,需要额外调整条件。
方法三:用GLOB匹配(兼容更低版本,功能有限)
如果连CAST的方法都觉得不够精准,还可以用SQLite的GLOB运算符(类似LIKE,但支持通配符*和?,区分大小写):
匹配整数
SELECT * FROM your_table WHERE your_column GLOB '[+-]?[0-9]*' AND your_column NOT GLOB '*[^0-9+-]*';
匹配浮点数
SELECT * FROM your_table WHERE (your_column GLOB '[+-]?[0-9]*.[0-9]*' OR your_column GLOB '[+-]?[0-9]+') AND your_column NOT GLOB '*[^0-9+-.]*';
不过这种方法没法支持科学计数法,适用场景比较有限,只适合简单的数值判断。
内容的提问来源于stack exchange,提问作者PChemGuy




