Oracle 解析来自 clob 的标签之间的数据

Oracle parsing data between tags from a clob

我遇到这样一种情况,应用程序将文本块存储在 CLOB 中。

每个文本块都被一个标签包围 [SYSDATE](请参阅下面的测试案例)。

我正在寻找可以提取匹配标签之间数据的查询。例如,如何获取 [11-22-2021 14:16:19] 之间的文本 所有比赛的标签。在这种情况下 'ZZZZZZZZZZZZZZZZZZZZ'

其次,有没有更好的方法来处理这种情况?也许可以使用 XML?非常感谢所有输入、想法和工作示例。


ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

CREATE table t(
seq_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
c CLOB DEFAULT ' ',
create_date DATE DEFAULT SYSDATE
);
/


insert into t (c) values (' ')
/


CREATE OR REPLACE PROCEDURE lob_append(
  p_clob IN OUT CLOB,
  p_text IN     VARCHAR2
)
AS
  l_text varchar2(32760);
  l_date_string VARCHAR2(50);
BEGIN

select '[' || TO_CHAR (SYSDATE, 'MM-DD-YYYY HH24:MI:SS') || ']'
    into l_date_string  from dual;

 
-- newline each time code is appended for clarity.
  l_text :=chr(10) || l_date_string || chr(10)
            || p_text || chr(10)
            || l_date_string||chr(10);

  dbms_lob.writeappend(p_clob, length(l_text), l_text );
END;
/
 

DECLARE
  l_clob CLOB := empty_clob();
lTime date;

BEGIN
lTime := sysdate;

  SELECT c INTO l_clob FROM t WHERE seq_num = 1 FOR UPDATE;

 lob_append(l_clob, rpad('Z',20,'Z'));

loop
        exit when sysdate = lTime + interval '5' second;
     end loop;

l_clob  := empty_clob();
SELECT c INTO l_clob FROM t WHERE seq_num = 1 FOR UPDATE;


lob_append(l_clob, rpad('Y',10,'Y'));


END;
/




SEQ_NUM    C    CREATE_DATE
1     
[11-22-2021 14:16:19]
ZZZZZZZZZZZZZZZZZZZZ
[11-22-2021 14:16:19]

[11-22-2021 14:16:24]
YYYYYYYYYY
[11-22-2021 14:16:24]
11222021 14:15:54


您的示例 CLOB 包含换行符;我认为这是正确的,并明确处理了换行符。 (下面的解决方案假定每个“令牌”本身不包含换行符 - 如果包含,那么您可以稍微修改 regexp_substr 调用,使用允许点元字符匹配换行符的选项。)

select t.seq_num, l.ord, l.token
from   t cross join lateral
       (
         select level as ord,
                regexp_substr(c, '(\[\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}])'
                                  || chr(10) || '(.*?)' || chr(10) || ''
                             , 1, level, null, 2) 
                as token
         from   dual
         connect by level <= 
                 regexp_count(c, '(\[\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}])'
                                  || chr(10) || '(.*?)' || chr(10) || '')
       ) l
order  by seq_num, ord   --  if needed
;


   SEQ_NUM        ORD TOKEN                    
---------- ---------- -------------------------
         1          1 ZZZZZZZZZZZZZZZZZZZZ     
         1          2 YYYYYYYYYY 

添加了create_date输出

SELECT  T.SEQ_NUM,
        L.ORD,
        L.CREATE_DATE,
        L.TOKEN
FROM  T,
        LATERAL(
                SELECT  LEVEL ORD,
                        REGEXP_SUBSTR(
                                      C,
                                      '\[(.{19})\]',
                                      1,
                                      LEVEL * 2 - 1,
                                      null,
                                      1
                                     ) CREATE_DATE,
                        REGEXP_SUBSTR(
                                      C,
                                      '(\[.{19}\])(' ||
                                      CHR(10) || '|' || CHR(13) || ')*(.*)(' ||
                                      CHR(10) || '|' || CHR(13) || ')',
                                      1,
                                      LEVEL,
                                      'n',
                                      3
                                     ) TOKEN
                  FROM  DUAL
                  CONNECT BY LEVEL <= REGEXP_COUNT(
                                                   C,
                                                   '(\[.{19}\])(' ||
                                                   CHR(10) || '|' || CHR(13) || ')*(.*)(' ||
                                                   CHR(10) || '|' || CHR(13) || ')'
                                                  )
               ) L
order  by seq_num, ord;

SEQ_NUM ORD CREATE_DATE TOKEN
1   1   12-01-2021 05:53:22 ZZZZZZZZZZZZZZZZZZZZ
1   2   12-01-2021 05:53:24 YYYYYYYYYY