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

发布于 2024-12-12 22:25:18 字数 125 浏览 1 评论 0 原文

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

I am trying to locate some problematic records in a very large Oracle table. The column should contain all numeric data even though it is a varchar2 column. I need to find the records which don't contain numeric data (The to_number(col_name) function throws an error when I try to call it on this column).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

时光暖心i 2024-12-19 22:25:18

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

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

I was thinking you could use a regexp_like condition and use the regular expression to find any non-numerics. I hope this might help?!

SELECT * FROM table_with_column_to_search WHERE REGEXP_LIKE(varchar_col_with_non_numerics, '[^0-9]+');
沙与沫 2024-12-19 22:25:18

要获取指示符:

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

例如

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

"contains char"

and

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

"number"

and

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”这样的非数字值,它将被忽略。

To get an indicator:

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"

and

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

"number"

and

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

"number"

Oracle 11g has regular expressions so you could use this to get the actual number:

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

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

If there is a non-numeric value like '23g' it will just be ignored.

零度° 2024-12-19 22:25:18

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

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

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 的方法来说,这会有点棘手。

);

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


要接受浮点...


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

);

要接受浮点...


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

);

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


要接受浮点...


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

);

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

);

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


要接受浮点...


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

);

要接受浮点...


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

);

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


要接受浮点...


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

In contrast to SGB's answer, I prefer doing the REGEXP_LIKE() defining the actual format of my data and negating that. This allows me to define values like '$DDD,DDD,DDD.DD'.

In the OPs simple scenario, it would look like...

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

...which finds all non-positive integers. If you want to accept negative integers also, it's an easy change, just add an optional leading minus...

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

To accept floating points...

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

Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

...which finds all non-positive integers. If you want to accept negative integers also, it's an easy change, just add an optional leading minus...


To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

...which finds all non-positive integers. If you want to accept negative integers also, it's an easy change, just add an optional leading minus...


To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

...which finds all non-positive integers. If you want to accept negative integers also, it's an easy change, just add an optional leading minus...


To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

);

...which finds all non-positive integers. If you want to accept negative integers also, it's an easy change, just add an optional leading minus...


To accept floating points...


Same goes further with any format. Basically, you will generally already have the formats to validate input data, so when you desire to find data that does not match that format ... it's simpler to negate that format than come up with another one; which in case of SGB's approach would be a bit tricky to do if you want more than just positive integers.

何以笙箫默 2024-12-19 22:25:18

用这个

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

Use this

SELECT * 
FROM TableToSearch 
WHERE NOT REGEXP_LIKE(ColumnToSearch, '^-?[0-9]+(\.[0-9]+)?
);
君勿笑 2024-12-19 22:25:18

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

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

 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

After doing some testing, i came up with this solution, let me know in case it helps.

Add this below 2 conditions in your query and it will find the records which don't contain numeric data

 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
飞烟轻若梦 2024-12-19 22:25:18

从 Oracle 12.2 开始,函数 to_number 有一个选项 ON CONVERSION ERROR 子句,可以捕获异常并提供默认值。

这可以用于数值测试。当转换失败时简单设置NULL并过滤所有非NULL值。

示例

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

Starting with Oracle 12.2 the function to_number has an option ON CONVERSION ERROR clause, that can catch the exception and provide default value.

This can be used for the test of number values. Simple set NULL when the conversion fails and filer all not NULL values.

Example

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
悲欢浪云 2024-12-19 22:25:18

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

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

如果有TRIM 之后字符串中剩下的任何内容都必须是非数字字符。

From http://www.dba-oracle.com/t_isnumeric.htm

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

If there is anything left in the string after the TRIM it must be non-numeric characters.

も星光 2024-12-19 22:25:18

我发现这很有用:

 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')

I've found this useful:

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

If the result is NULL, it's numeric (ignoring floating point numbers.)

However, I'm a bit baffled why the underscore is needed. Without it the following also returns null:

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

There is also one of my favorite tricks - not perfect if the string contains stuff like "*" or "#":

 SELECT 'is a number' FROM dual WHERE UPPER('123') = LOWER('123')
输什么也不输骨气 2024-12-19 22:25:18

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

方法 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]+
);

After doing some testing, building upon the suggestions in the previous answers, there seem to be two usable solutions.

Method 1 is fastest, but less powerful in terms of matching more complex patterns.
Method 2 is more flexible, but slower.

Method 1 - fastest
I've tested this method on a table with 1 million rows.
It seems to be 3.8 times faster than the regex solutions.
The 0-replacement solves the issue that 0 is mapped to a space, and does not seem to slow down the query.

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

Method 2 - slower, but more flexible
I've compared the speed of putting the negation inside or outside the regex statement. Both are equally slower than the translate-solution. As a result, @ciuly's approach seems most sensible when using regex.

SELECT *
FROM <table>
WHERE NOT REGEXP_LIKE(<char_column>, '^[0-9]+
);
听闻余生 2024-12-19 22:25:18

您可以使用以下一项检查:

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;

You can use this one check:

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;
情何以堪。 2024-12-19 22:25:18

输入图片这里的描述我用有问题的列进行托盘排序,并找到带有列的行。

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

enter image description hereI tray order by with problematic column and i find rows with column.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文