Oracle 是不是提供从已解析的字符串/clob 行返回多个子字符串的方法?

Posted

技术标签:

【中文标题】Oracle 是不是提供从已解析的字符串/clob 行返回多个子字符串的方法?【英文标题】:Does Oracle provide the way of returning multiple substrings from a string/clob row that has been parsed?Oracle 是否提供从已解析的字符串/clob 行返回多个子字符串的方法? 【发布时间】:2011-11-11 20:16:53 【问题描述】:

我知道有 REGEXP_ 函数,但是当简单地应用于字符串 var 时,这些函数最多返回 1 行。我知道你可以在 WHERE 子句中使用它,但我需要一种处理大字符串/文本/clob vars 而不是表的方法,所以我想知道某个函数是否可以以某种方式返回多个子字符串(我在想什么比如 php 中的 explode() 或 - 甚至更好 - preg_match()。 正如 APC 建议的那样,我提供了一个示例字符串和我想要获得的结果示例。 就像我在下面的 cmets 中所说的那样,我想像这样获得函数/过程体(某些包的一部分的函数/过程):

字符串:

  create or replace PACKAGE BODY export_db IS
  FUNCTION o_functie(ceva NUMBER) return boolean IS
  BEGIN
    RETURN null;
  END;
  FUNCTION o_functie(ceva NUMBER, altceva VARCHAR2) return boolean IS
  BEGIN
    RETURN null;
  END;
  PROCEDURE export_db_tabele IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT object_type,object_name FROM user_objects where object_type IN ( 'TABLE')) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl(c.object_type, c.object_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('tabele', v_ddl);
  END;
  PROCEDURE export_db_restrictii IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT constraint_name FROM user_constraints) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('CONSTRAINT', c.constraint_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('restrictii', v_ddl);
  END;
  PROCEDURE export_db_secvente IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT sequence_name FROM user_sequences) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('SEQUENCE', c.sequence_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('secvente', v_ddl);
  END;
  PROCEDURE export_db_proceduri IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects up WHERE object_type = 'PROCEDURE') LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('PROCEDURE', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP;  
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('proceduri', v_ddl);
  END;
  PROCEDURE export_db_functii IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'FUNCTION' ) LOOP 
         v_ddl := v_ddl || dbms_metadata.get_ddl('FUNCTION', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('functii', v_ddl);
  END;
  PROCEDURE export_db_pachete IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'PACKAGE' ) LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('PACKAGE', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP;   
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('pachete', v_ddl);
  END;
  PROCEDURE export_db_declansatoare IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT OBJECT_NAME FROM user_objects uo WHERE object_type = 'TRIGGER' ) LOOP 
        v_ddl := v_ddl || dbms_metadata.get_ddl('TRIGGER', c.OBJECT_NAME)||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('declansatoare', v_ddl);
  END;
END;

结果是:

例如:

  FUNCTION o_functie(ceva NUMBER, altceva VARCHAR2) return boolean IS
  BEGIN
    RETURN null;
  END;

PROCEDURE export_db_secvente IS
    v_ddl CLOB;
  BEGIN
      FOR c IN(SELECT sequence_name FROM user_sequences) LOOP
        v_ddl := v_ddl || dbms_metadata.get_ddl('SEQUENCE', c.sequence_name)||';'||CHR(13)||CHR(10);   
      END LOOP; 
      INSERT INTO dbexport(tipobiect, ddltext) VALUES ('secvente', v_ddl);
  END;

如果您知道获取这些过程/函数的任何其他方法,我很高兴放弃解析所有这些 - 据我所知 - 没有选择可以这样做......甚至来自 user_source、user_procedures 表或其他。 ..

【问题讨论】:

Does PL/SQL have an equivalent StringTokenizer to Java's? 的可能重复项 我不是 PHP 专家,但 PREG_MATCH() 和 EXPLODE() 似乎会产生不同的结果。因此,如果您能给我们一个示例字符串和您想要的结果,那将非常有用。 @APC 该字符串将是一个包主体,因为在 Oracle 中,我无法找到一种方法来获取第一个内部的函数/过程主体,就像您可以在主模式中获取的那样(女巫不在包裹中)。因此我需要解析字符串... 也许我很密集,但我真的不明白这意味着什么。你举个例子真的很难吗? 【参考方案1】:

可能是这样的:

CREATE OR REPLACE FUNCTION explode(longline varchar)
  RETURN sys.dbms_debug_vc2coll PIPELINED
IS  
  pos PLS_INTEGER;
  lastpos PLS_INTEGER;
  element varchar(2000);
BEGIN
   lastpos := 1;
   pos := instr(longline, ',');

   while pos > 0 loop
      element := substr(longline, lastpos, pos - lastpos);
      lastpos := pos + 1;
      pos := instr(longline, ',', lastpos);
      pipe row(element);
   end loop;

   if lastpos <= length(longline) then
      pipe row (substr(longline, lastpos));
   end if;

   RETURN;
END;  
/

可以这样使用:

SQL> select * from table(explode('1,2,3')); COLUMN_VALUE --------------------------------------------- 1 2 3 SQL>

如果您不在 11.x 上,则需要自己定义返回类型:

create type char_table as table of varchar(4000);

并将函数声明更改为:

CREATE OR REPLACE FUNCTION explode(longline varchar)
  RETURN char_table pipelined
.....

【讨论】:

非常感谢!虽然我需要更多可调整的东西,所以我可以得到基于变量分隔符的子字符串......我会看看我是否可以让这个工作为我工作!再次感谢! 只需将分隔符作为参数传递给函数。 是的,我在函数中添加了一个新参数(分隔符),因为没有与我需要的子字符串完全匹配的分隔符,我不得不使用 REGEXP_ 函数在字符串爆炸。更具体地说(如果这可以帮助某人),在包体中,您有更多以“PROC..”或“FUNC..”开头并以“;”结尾的过程/函数。但是在一个特定的程序里面可能会有很多其他的“;”你不能用“;”来爆炸。所以我使用 REGEXP_REPLACE 在任何“;”之间创建一个新的专用分隔符和“程序”或“功能”。

以上是关于Oracle 是不是提供从已解析的字符串/clob 行返回多个子字符串的方法?的主要内容,如果未能解决你的问题,请参考以下文章

php如何读取clob字段

oracle中 怎么把字符串的数据insert 到 clob类型的字段中

使用休眠和 Oracle 将 Clob 转换为字符串

JSP中的Oracle clob到字符串

oracle中blob,clob,nclob主要区别是啥?

如何在 Oracle 中获取 CLOB 列的字节大小?