替换与Oracle中的模式不匹配的Text

时间:2013-06-27 10:10:01

标签: oracle

我在表格中的CLOB中有下面的文字
表名:tbl1

col1 - 数字(主键)
col2 - clob(如下)

列#1
-----
Col1 = 1
Col2 =
1331882981,ab123456,这里的一些文字
它可以运行多行并且有很多文本...
~1331890329,pqr123223,更多文字......

列#2
-----
Col1 = 2
Col2 =
1331882981,abc333,这里的一些文字
它可以运行多行并且有很多文本...
~1331890329,pqrs23,更多文字......


现在我需要知道如何才能得到低于输出的信息
Col1值
---- ---------------------
1 1331882981,ab123456
1 1331890329,pqr123223
2 1331882981,abc333
2 1331890329,pqrs23


([0-9] {10},[a-z 0-9] +。),==>这是匹配“1331890329,pqrs23”的正则表达式,我需要知道如何替换哪些不匹配此正则表达式然后将它们分成多行

修改#1
我在Oracle 10.2.0.5.0上,因此不能使用REGEXP_COUNT函数:-(另外,col2是一个很大的CLOB

修改#2
我试过下面的查询,它适用于某些记录(即如果我添加“where”子句)。但是当我删除“where”时,它永远不会返回任何结果。我试图将它放入一个视图并插入一个表并让它一夜之间运行但仍然没有完成:(

with t as (select col1, col2 from temp_table)
select col1,
       cast(substr(regexp_substr(col2, '[^~]+', 1, level), 1, 50) as
            varchar2(50)) data
  from t
connect by level <= length(col2) - length(replace(col2, '~')) + 1



修改#3

# of Chars in Clob      Total
-----------             -----
0 - 1k                  3196
1k - 5k                 2865
5k - 25k                 661
25k - 100k                36
> 100k                     2
-----------             -----
Grand Total             6760

我有~7k行的clobs,其分布如上所示...

2 个答案:

答案 0 :(得分:1)

好吧,你可以试试像:

with v as
(
  select 1 col1, '1331882981,ab123456,Some text here
which can run multiple lines and have a lot of text...
~1331890329,pqr123223,Some more text...' col2 from dual
  union all
  select 2 col1, '133188298777,abc333,Some text here
which can run multiple lines and have a lot of text...
~1331890329,pqrs23,Some more text...' col2 from dual
)
select distinct col1, regexp_substr(col2, '([0-9]{10},[a-z 0-9]+)', 1, level) split
from v
connect by level <= REGEXP_COUNT(col2, '([0-9]{10},[a-z0-9]+)')
order by col1
;

这给出了:

1   1331882981,ab123456
1   1331890329,pqr123223
2   1331890329,pqrs23
2   3188298777,abc333

编辑 10g,REGEXP_COUNT不存在,但您有workarounds。在这里,我替换了我希望在文本中找不到的模式(这里,XYZXYZ,但你可以选择更复杂的东西来自信),做一个具有相同匹配的差异但被替换为空字符串,然后除以我的模式长度(此处为6):

with v as
(
  select 1 col1, '1331882981,ab123456,Some text here
which can run multiple lines and have a lot of text...
~1331890329,pqr123223,Some more text...' col2 from dual
  union all
  select 2 col1, '133188298777,abc333,Some text here
which can run multiple lines and have a lot of text...
~1331890329,pqrs23,Some more text...' col2 from dual
)
select distinct col1, regexp_substr(col2, '([0-9]{10},[a-z 0-9]+)', 1, level) split
from v
connect by level <= (length(REGEXP_REPLACE(col2, '([0-9]{10},[a-z 0-9]+)', 'XYZXYZ')) - length(REGEXP_REPLACE(col2, '([0-9]{10},[a-z 0-9]+)', ''))) / 6
order by col1
;

编辑2: CLOB(以及一般的LOB)和正则表达似乎不太合适:

ORA-00932: inconsistent datatypes: expected - got CLOB

将CLOG转换为字符串(regexp_substr(to_char(col2), ...)似乎解决了这个问题。

编辑3: CLOB也不喜欢distinct,因此在嵌入式请求中将split result转换为char,然后在上层请求中使用distinct成功!

select distinct col1, split from
(
    select col1, to_char(regexp_substr(col2, '([0-9]{10},[a-z 0-9]+)', 1, level)) split
    from temp_epn
    connect by level <= (length(REGEXP_REPLACE(col2, '([0-9]{10},[a-z 0-9]+)', 'XYZXYZ')) - length(REGEXP_REPLACE(col2, '([0-9]{10},[a-z 0-9]+)', ''))) / 6
    order by col1
);

答案 1 :(得分:0)

以上解决方案无效,以下是我的工作。

update temp_table set col2=regexp_replace(col2,'([0-9]{10},[a-z0-9]+)','(\1)') ;
update temp_table set col2=regexp_replace(col2,'\),[\s\S]*~\(','(\1)$');
update temp_table set col2=regexp_replace(col2,'\).*?\(','$');
update temp_table set col2=replace(regexp_replace(col2,'\).*',''),'(','');

在这4个更新命令之后,col2将具有类似

的内容
1 1331882981,ab123456$1331890329,pqr123223
2 1331882981,abc333$1331890329,pqrs23

然后我写了一个函数来分割这个东西。我选择该功能的原因是拆分“$”以及col2仍然具有> 10k字符的事实

create or replace function parse( p_clob in clob ) return sys.odciVarchar2List
pipelined
as
        l_offset number := 1;
        l_clob   clob := translate( p_clob, chr(13)|| chr(10) || chr(9), '   ' ) || '$';
        l_hit    number;
begin
        loop
          --Find occurance of "$" from l_offset
          l_hit := instr( l_clob, '$', l_offset );
          exit when nvl(l_hit,0) = 0;
          --Extract string from l_offset to l_hit
          pipe row ( substr(l_clob, l_offset , (l_hit - l_offset)) );
          --Move offset
          l_offset := l_hit+1;
        end loop;
end;
然后我打电话给

select col1,
       REGEXP_SUBSTR(column_value, '[^,]+', 1, 1) col3,
       REGEXP_SUBSTR(column_value, '[^,]+', 1, 2) col4
  from temp_table, table(parse(temp_table.col2));