每当字符串l_long_string
的长度超过4000个字符时,以下代码就会抛出错误:
ORA-01460: unimplemented or unreasonable conversion requested
当我尝试使用
时,而不是嵌套的regexp_substr
查询
SELECT column_value
FROM TABLE(l_string_coll)
它扔了:
ORA-22905: cannot access rows from a non-nested table item
如何修改动态查询?
注意:
- l_string_coll
类型为DBMS_SQL.VARCHAR2S
,并作为我的过程的输入(此处,我刚刚显示为匿名块)
- 我必须在不在DB模式中创建用户定义类型的情况下进行管理,因此我使用的是内置DBMS_SQL.VARCHAR2S
。
- 这不是实际的业务流程,但接近于此。 (不能发布原文)
- 动态查询必须存在,因为我使用它来构建具有会话,当前应用程序模式名称等的实际查询。
/*
CREATE TABLE some_other_table
(word_id NUMBER(10), word_code VARCHAR2(30), word VARCHAR2(255));
INSERT INTO some_other_table VALUES (1, 'A', 'AB');
INSERT INTO some_other_table VALUES (2, 'B', 'BC');
INSERT INTO some_other_table VALUES (3, 'C', 'CD');
INSERT INTO some_other_table VALUES (4, 'D', 'DE');
COMMIT;
*/
DECLARE
l_word_count NUMBER(10) := 0;
l_counter NUMBER(10) := 0;
l_long_string VARCHAR2(30000) := NULL;
l_dyn_query VARCHAR2(30000) := NULL;
l_string_coll DBMS_SQL.VARCHAR2S;
BEGIN
-- l_string_coll of type DBMS_SQL.VARCHAR2S comes as Input to the procedure
FOR i IN 1 .. 4100
LOOP
l_counter := l_counter + 1;
l_string_coll(l_counter) := 'AB';
END LOOP;
-- Above input collection is concatenated into CSV string
FOR i IN l_string_coll.FIRST .. l_string_coll.LAST
LOOP
l_long_string := l_long_string || l_string_coll(i) || ', ';
END LOOP;
l_long_string := TRIM(',' FROM TRIM(l_long_string));
dbms_output.put_line('Length of l_long_string = ' || LENGTH(l_long_string));
/*
Some other tasks in PLSQL done successfully using the concatenated string l_long_string
*/
l_dyn_query := ' SELECT COUNT(*)
FROM some_other_table
WHERE word IN ( SELECT TRIM(REGEXP_SUBSTR(str, ''[^,]+'', 1, LEVEL)) word
FROM ( SELECT :string str FROM SYS.DUAL )
CONNECT BY TRIM(REGEXP_SUBSTR(str, ''[^,]+'', 1, LEVEL)) IS NOT NULL )';
--WHERE word IN ( SELECT column_value FROM TABLE(l_string_coll) )';
EXECUTE IMMEDIATE l_dyn_query INTO l_word_count USING l_long_string;
dbms_output.put_line('Word Count = ' || l_word_count);
EXCEPTION
WHEN OTHERS
THEN
dbms_output.put_line('SQLERRM = ' || SQLERRM);
dbms_output.put_line('FORMAT_ERROR_BAKCTRACE = ' || dbms_utility.format_error_backtrace);
END;
/
答案 0 :(得分:0)
如何修改动态查询?
首先。根据您提供的代码,完全不需要使用动态,本机或DBMS_SQL
动态SQL。
其次,SQL不能对长度大于4K字节的“字符串”(12c之前的Oracle版本)或32K字节(Oracle版本12cR1及更高版本,如果MAX_STRING_SIZE
初始化参数设置为{ {1}})。
EXTENDED
个字符串。如果你只需要用逗号分隔的sting计算单词,你可以简单地使用varchar2()
正则表达式函数(Oracle 11gr1及更高版本),如下所示:
regexp_count()
结果:
set serveroutput on;
set feedback off;
clear screen;
declare
l_str varchar2(100) := 'aaa,bb,ccc,yyy';
l_numOfWords number;
begin
l_numOfWords := regexp_count(l_str, '[^,]+');
dbms_output.put('Number of words: ');
dbms_output.put_line(to_char(l_numOfWords));
end;