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

时间:2011-10-31 17:39:41

标签: sql oracle varchar numeric varchar2

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

10 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:11)

获得指标:

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

e.g。

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',则会被忽略。

答案 2 :(得分:5)

与SGB的答案相反,我更喜欢使用正则表达式定义数据的实际格式并否定它。这允许我定义$ DDD,DDD,DDD.DD等值 在OPs的简单场景中,它看起来像

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]+$');

接受浮点......

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

任何格式都相同。基本上,您通常已经拥有验证输入数据的格式,因此当您希望找到与该格式不匹配的数据时...否则更容易否定该格式而不是另一种格式;如果你想要的不仅仅是正整数,那么在SGB方法的情况下做起来会有点棘手。

答案 3 :(得分:4)

使用此

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

答案 4 :(得分:2)

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

LENGTH(TRIM(TRANSLATE(, ' +-.0123456789', ' '))) is null

如果在TRIM之后字符串中还有任何内容,则它必须是非数字字符。

答案 5 :(得分:0)

我发现这很有用:

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

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

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

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

还有一个我最喜欢的技巧 - 如果字符串包含“*”或“#”之类的内容,则不完美:

 SELECT 'is a number' FROM dual WHERE UPPER('123') = LOWER('123')

答案 6 :(得分:0)

在做了一些测试之后,根据之前答案中的建议,似乎有两个可用的解决方案。

方法1最快,但在匹配更复杂的模式方面效率较低 方法2更灵活,但速度更慢。

方法1 - 最快
我已经在一个有100万行的桌子上测试了这种方法 它似乎比正则表达式解决方案快3.8倍 0替换解决了0映射到空间的问题,并且似乎不会减慢查询速度。

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

方法2 - 更慢,但更灵活
我已经比较了在正则表达式声明之内或之外放置否定的速度。两者都比翻译解决方案慢。因此,使用正则表达式时,@ ciuly的方法似乎最明智。

SELECT *
FROM <table>
WHERE NOT REGEXP_LIKE(<char_column>, '^[0-9]+$');

答案 7 :(得分:0)

你可以使用这一项检查:

create or replace function to_n(c varchar2) return number is
begin return to_number(c);
exception when others then return -123456;
end;

select id, n from t where to_n(n) = -123456;

答案 8 :(得分:0)

在做了一些测试之后,我想出了这个解决方案,如果它有帮助,请告诉我。

在查询中添加以下两个条件,它会找到不包含数字数据的记录

 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

答案 9 :(得分:0)

enter image description here我用有问题的列进行托盘排序,我找到带有列的行。

SELECT 
 D.UNIT_CODE,
         D.CUATM,
         D.CAPITOL,
          D.RIND,
          D.COL1  AS COL1


FROM
  VW_DATA_ALL_GC  D
  
  WHERE
  
   (D.PERIOADA IN (:pPERIOADA))  AND   
   (D.FORM = 62) 
   AND D.COL1 IS NOT NULL
 --  AND REGEXP_LIKE (D.COL1, '\[\[:alpha:\]\]')
 
-- AND REGEXP_LIKE(D.COL1, '\[\[:digit:\]\]')
 
 --AND REGEXP_LIKE(TO_CHAR(D.COL1), '\[^0-9\]+')
 
 
   GROUP BY 
    D.UNIT_CODE,
         D.CUATM,
         D.CAPITOL,
          D.RIND ,
          D.COL1  
         
         
        ORDER BY 
        D.COL1