在Oracle中查找不包含数字数据的行

问题描述 投票:0回答:11

我试图在一个非常大的 Oracle 表中找到一些有问题的记录。即使该列是 varchar2 列,也应包含所有数值数据。我需要找到不包含数字数据的记录(当我尝试在此列上调用 to_number(col_name) 函数时,它会抛出错误)。

sql oracle varchar numeric varchar2
11个回答
29
投票

我想你可以使用 regexp_like 条件并使用正则表达式来查找任何非数字。我希望这会有所帮助?!

SELECT * FROM table_with_column_to_search WHERE REGEXP_LIKE(varchar_col_with_non_numerics, '[^0-9]+');

14
投票

获取指标:

DECODE( TRANSLATE(your_number,' 0123456789',' ')

例如

SQL> select DECODE( TRANSLATE('12345zzz_not_numberee',' 0123456789',' '), NULL, 'number','contains char')
 2 from dual
 3 /

"contains char"

SQL> select DECODE( TRANSLATE('12345',' 0123456789',' '), NULL, 'number','contains char')
 2 from dual
 3 /

"number"

SQL> select DECODE( TRANSLATE('123405',' 0123456789',' '), NULL, 'number','contains char')
 2 from dual
 3 /

"number"

Oracle 11g 有正则表达式,因此您可以使用它来获取 实际数字

SQL> SELECT colA
  2  FROM t1
  3  WHERE REGEXP_LIKE(colA, '[[:digit:]]');

COL1
----------
47845
48543
12
...

如果有像“23g”这样的非数字值,它将被忽略。


14
投票

与 SGB 的答案相反,我更喜欢定义数据的实际格式并否定它。这允许我定义像“$DDD,DDD,DDD.DD”这样的值。

在 OP 的简单场景中,它看起来像......
REGEXP_LIKE()

...查找所有非正整数。如果您也想接受负整数,这是一个简单的更改,只需添加一个可选的前导减号...

SELECT * 
FROM table_with_column_to_search 
WHERE NOT REGEXP_LIKE(varchar_col_with_non_numerics, '^[0-9]+$');

接受浮点数...

SELECT * 
FROM table_with_column_to_search 
WHERE NOT REGEXP_LIKE(varchar_col_with_non_numerics, '^-?[0-9]+$');

任何格式都同样如此。基本上,您通常已经拥有验证输入数据的格式,因此当您希望查找与该格式不匹配的数据时……否定该格式比提出另一种格式更简单;如果您想要的不仅仅是正整数,那么对于 SGB 的方法来说,这会有点棘手。


用这个


4
投票

经过一些测试,我想出了这个解决方案,如果有帮助请告诉我。

4
投票

SELECT * FROM TableToSearch WHERE NOT REGEXP_LIKE(ColumnToSearch, '^-?[0-9]+(\.[0-9]+)?$');

从 Oracle 12.2 开始,函数 
to_number

3
投票
and REGEXP_LIKE(<column_name>, '\D') -- this selects non numeric data and not REGEXP_LIKE(column_name,'^[-]{1}\d{1}') -- this filters out negative(-) values

子句,可以捕获异常并提供默认值。 这可以用于数值的测试。当转换失败时简单设置

ON CONVERSION ERROR
并过滤所有

not NULL

值。

示例

NULL

来自 
http://www.dba-oracle.com/t_isnumeric.htm

1
投票

with num as ( select '123' vc_col from dual union all select '1,23' from dual union all select 'RV12P2000' from dual union all select null from dual) select vc_col from num where /* filter numbers */ vc_col is not null and to_number(vc_col DEFAULT NULL ON CONVERSION ERROR) is not null ; VC_COL --------- 123 1,23 如果 TRIM 之后字符串中剩下任何内容,则它必须是非数字字符。


我发现这很有用:


0
投票

如果结果为 NULL,则它是数字(忽略浮点数。)

但是,我有点困惑为什么需要下划线。如果没有它,以下内容也会返回 null:

select translate('your string','_0123456789','_') from dual

还有我最喜欢的技巧之一 - 如果字符串包含“*”或“#”之类的东西,那就不完美:

 select translate('s123','0123456789', '') from dual

经过一些测试,根据前面答案中的建议,似乎有两个可用的解决方案。

0
投票
方法2更灵活,但速度较慢。

方法1 - 最快

我已经在一个有 100 万行的表上测试了这个方法。

它似乎比正则表达式解决方案快 3.8 倍。 0替换解决了0映射到空格的问题,并且似乎并没有减慢查询速度。
SELECT 'is a number' FROM dual WHERE UPPER('123') = LOWER('123')

方法2 - 速度较慢,但更灵活

我比较了将否定放在正则表达式语句内部或外部的速度。两者都比翻译解决方案同样慢。因此,在使用正则表达式时,@ciuly 的方法似乎最明智。

SELECT * FROM <table> WHERE TRANSLATE(replace(<char_column>,'0',''),'0123456789',' ') IS NOT NULL;

您可以使用这张支票:

0
投票


© www.soinside.com 2019 - 2024. All rights reserved.