Sql 我需要只显示varchar2数据类型列中的数值,而不使用任何正则表达式

Sql 我需要只显示varchar2数据类型列中的数值,而不使用任何正则表达式,sql,oracle,Sql,Oracle,表名SAMP_TAB-它只有一个数据类型为varchar2的列COL-数据如下: COL ---- 1234 abcd 098 12wer 345 这些是该列中的上述示例值 现在我想写一个查询,它将只从这个列返回数值 期望输出: 1234 098 345 我想在不使用任何正则表达式的情况下编写该查询。假设您由于某种原因无法使用正则表达式: SELECT COL FROM SAMP_TAB WHERE TRIM(TRANSLATE(COL, '0123456789', ' ')) IS NU

表名SAMP_TAB-它只有一个数据类型为varchar2的列COL-数据如下:

COL
----
1234
abcd
098
12wer
345
这些是该列中的上述示例值

现在我想写一个查询,它将只从这个列返回数值

期望输出:

1234
098
345 

我想在不使用任何正则表达式的情况下编写该查询。

假设您由于某种原因无法使用正则表达式:

SELECT COL
FROM SAMP_TAB
WHERE TRIM(TRANSLATE(COL, '0123456789', ' ')) IS NULL;
如果您可以使用regex,那么将REGEXP_与模式^[0-9]+$一起使用:

或者:

SQL> with test (col) as
  2    (select '1234'  from dual union all
  3     select 'abcd'  from dual union all
  4     select '098'   from dual union all
  5     select '12wer' from dual union all
  6     select '1ab3'  from dual union all
  7     select '345'   from dual
  8    )
  9  select col
 10  from test
 11  where translate(col, 'a0123456789', 'a') is null;

COL
-----
1234
098
345

SQL>

拆分每个字符,通过ascii函数过滤提取整数 ascii介于48和57之间,重新组合字符串可能是另一种选择:

with t as
(      
 select substr(col,level,1) as chr, level as lvl,
        row_number() over (order by 0) as rn
   from samp_tab
  connect by level <= length(col)
      and prior sys_guid() is not null
      and prior col = col
), t2 as
(
select t.*, sum(case when lvl=1 then 1 else 0 end) over (order by rn) as rn2 
  from t
 where ascii(chr) between 48 and 57
)
select listagg(chr) within group (order by rn2) as new_col
  from t2
 group by rn2;

如果您使用的是12c R2或更高版本,并且应该使用,则可以使用内置函数validate_conversion,这是确定值是否可以转换为其他数据类型的安全方法

像这样:

select * from samp_table
where validate_conversion(col as number) = 1
/
与使用regex或translate的解决方案相比,这种方法有一个主要优势,即它测试字符串的计算结果是否为数值,而其他解决方案则会阻塞,例如,1.234E+10这样的指数表达式。或者可能传递一个IP地址,如127.0.0.1

如果您使用的是Oracle的早期版本,则可以编写一个用户定义的函数,该函数用于计算传递的参数:

create or replace function is_number (p_str in varchar2) return pls_integer
is
  rv pls_integer;
begin

  declare
    n number;
  begin

    n := to_number(p_str);
    rv := 1; -- p_str is a number

  exception
    when others then
      rv := 0; -- p_str is not a number
  end;

  return rv;

end;
/

您可以在WHERE子句中调用此函数,与上面示例中的validate_conversion相同。

OP在没有使用任何reg-exp的情况下说的。我觉得这个要求有点可疑。为什么OP不想使用正则表达式,因为这是处理此需求的最佳方法,除非是家庭作业问题等?请参阅下面的@APC答案。至于fishy,我认为家庭作业可以解释这一点-
create or replace function is_number (p_str in varchar2) return pls_integer
is
  rv pls_integer;
begin

  declare
    n number;
  begin

    n := to_number(p_str);
    rv := 1; -- p_str is a number

  exception
    when others then
      rv := 0; -- p_str is not a number
  end;

  return rv;

end;
/