我有一个文本类型的列,其中包含随机值。其中一些是数字,一些是文本,还有一些是文本和数字的混合。我试图将它们区分为:
myfield is_numeric
____________________
-4 true
0004 true
4.00 true
dog false
D04 false
04f false
而其他的是名字和其他字符串。我用的是正则表达式
SELECT id,
myfield
(myfield::varchar~ '^-?[0-9]*.?[0-9]*$') is_numeric
FROM mytable
但是,我注意到像D04
和04c
这样的值对于该正则表达式返回true
,对于我的用例来说,这是一个误报。
为什么会出现这种情况?看起来^
不一定匹配整个值,而是匹配该值的任何有效子字符串。然而,像D04f
这样的值确实返回false
,因此即使字段中存在数字子字符串,^
和$
运算符的组合也能完成它的工作。
我暂时使用:
SELECT id,
myfield
(myfield::varchar ~ '^-?[0-9]*.?[0-9]*$'
AND myfield::varchar !~ '[^0-9\-\.]') is_numeric
FROM mytable
但这似乎是无效的(并且不排除双点),我仍然想知道为什么正则表达式正确地排除了以非数字字符开头和结尾的字符串,而对只包含尾随或前导非数字字符的字符串错误地返回true。
2条答案
按热度按时间pbpqsu0x1#
这对你有用吗?
我假定
-0.07.5
是无效的(出现双点)。D04
也将返回false。原始正则表达式的问题是没有转义点,因此它将匹配任何字符,包括
D04
中的D
。希望能有所帮助。
vltsax252#
任何基于正则表达式的解决方案最多只能重新发明PostgreSQL自己的逻辑,用于将
text
转换为numeric
(或任何其他类型)。为了与PostgreSQL自己的类型定义保持一致,最简单的方法是直接使用它:
更一般的形式:
请注意,无论参数和/或类型是否无效,都将返回
false
。Demo