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 行返回多个子字符串的方法?的主要内容,如果未能解决你的问题,请参考以下文章