如何使用Oracle分割CLOB对象,并将:Oracle中的分隔符分割为多个记录

时间:2016-07-15 11:38:07

标签: regex oracle substr oracle12c regexp-substr

我有一个CLOB对象示例,如下所示。我想首先使用分隔符“,”将其拆分,然后将其保存在临时表中供以后使用。

ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0

我想在每行中以下面的格式保存结果。

Column_Name
__________________________
ABCDEF:PmId12345RmLn1VlId0
ABCDEF:PmId12345RmLn1VlId0
ABCDEF:PmId12345RmLn1VlId0

我尝试使用REGEXP_SUBSTR功能

select 
    regexp_substr('ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0', '[^,]+', 1, 1) Column_Name 
from dual;

上面的查询给我单个记录,如下所示

Column_Name
__________________________
ABCDEF:PmId12345RmLn1VlId0

任何人都可以帮我解决这个问题。

2 个答案:

答案 0 :(得分:4)

以下是使用递归因式子查询(Oracle 11.2及更高版本)的解决方案:

with inputs ( str ) as (
       select to_clob('ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0')
       from dual
     ),
     prep ( s, n, token, st_pos, end_pos ) as (
       select ',' || str || ',', -1, null, null, 1
         from inputs
       union all
       select s, n+1, substr(s, st_pos, end_pos - st_pos),
              end_pos + 1, instr(s, ',', 1, n+3)
         from prep
         where end_pos != 0
     )
select n as idx, token as column_name
from   prep
where  n > 0;



   IDX COLUMN_NAME
------ ----------------------------
     1 ABCDEF:PmId12345RmLn1VlId0
     2 ABCDEF:PmId12345RmLn1VlId0
     3 ABCDEF:PmId12345RmLn1VlId0
     4 ABCDEF:PmId12345RmLn1VlId0
     5 ABCDEF:PmId12345RmLn1VlId0

备注

你说CLOB但是在你的例子中你是从varchar2字符串中提取的。我添加了to_clob()以查看它是否/如何在CLOB上运行。

我使用了instrsubstr,因为他们经常(通常是?)在他们的regexp等价物之间表现得更好和更好。

我保存了输入字符串中每个子字符串的“索引”;在某些情况下,输入字符串中的标记顺序很重要。 (不是在你的例子中,你只重复了五次相同的标记。)

如果您需要更好的性能,特别是如果您的CLOB非常大,那么最好使用dbms_lob.substrdbms_lob.instr - 请参阅Performance of SUBSTR on CLOB,尤其是Alex Poole的回答,以及此处的文档:http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_lob.htm#BABEAJAD。请注意语法差异与常规substr / instr

答案 1 :(得分:-1)

以防万一你真的只想按照你的例子解析一个长字符串。如果需要在列表中查看值的索引,请在select中包含“level”:

using (SqlCommand command = 
    new SqlCommand("select * from gelirler where borc_tarihi between @begin_time and @end_time", connection))
{
    command.Parameters.Add("@begin_time", SqlDbType.Datetime);
    command.Parameters["@begin_time"].Value = datetimePicker1.Text;

    command.Parameters.Add("@end_time", SqlDbType.Datetime);
    command.Parameters["@end_time"].Value = datetimePicker2.Text;
    /* execute the query... */
}