2017-02-15 97 views
0

当使用给出DBMS_OUTPUT.CHARARR结果的DBMS_OUTPUT.GET_LINES时,如何将其转换为varchar2?我想使用DBMS_OUTPUT.GET_LINES来获取我的所有DBMS_PUTLINE语句,并将它们作为字符串返回给调用程序。如何将DBMS_OUTPUT.GET_LINES转换为VARCHAR2?

数据库:Oracle 12c中

PLSQL版本:版本11.0.6.1776

declare 
    -- Non-scalar parameters require additional processing 

    v_Data  DBMS_OUTPUT.CHARARR; 
    v_NumLines NUMBER; 
begin 
    -- Call the procedure 


    -- Procedure that will generate DMBS_OUTPUT.PUT_LINEs 
    executeProcFoo(); 

    v_NumLines := 1000; 
    DBMS_OUTPUT.GET_LINES(v_Data, v_NumLines); 

    FOR v_Counter IN 1..v_NumLines LOOP 
     --output putlines from get_lines 
     DBMS_OUTPUT.put_line(v_Data(v_Counter)); 
    END LOOP; 
end; 
+0

'dbms_output.chararr'已经是一个'varchar2'数组。你把它转换成'varchar2'是什么意思?你想要一个长串吗?或者您是否需要将其发布为与您的调用框架更兼容的其他集合类型? –

+0

是一个长字符串。我想将结果作为一个字符串返回给调用的Java应用程序。 – haju

+0

为什么?当然Java有数组?但无论如何,只需循环遍历数组,将其附加到合适的文本变量。我仍然没有看到技术问题。 –

回答

0

试试这个:

DECLARE 
    -- Non-scalar parameters require additional processing 

    v_Data  DBMS_OUTPUT.CHARARR; 
    v_NumLines NUMBER; 

    TYPE v IS TABLE OF VARCHAR2 (1000) 
       INDEX BY BINARY_INTEGER; 

    v_var  v; 
BEGIN 
    -- Call the procedure 


    -- Procedure that will generate DMBS_OUTPUT.PUT_LINEs 
    DBMS_OUTPUT.PUT_LINE ('vvvv'); 
    DBMS_OUTPUT.put_line ('xxxxx'); 

    v_NumLines := 1000; 
    DBMS_OUTPUT.GET_LINES (v_Data, v_NumLines); 

    FOR v_Counter IN v_data.FIRST .. v_data.LAST 
    LOOP 
     --output putlines from get_lines 
     DBMS_OUTPUT.put_line (v_Data (v_Counter)); 
     v_var (v_counter) := v_data (v_counter); 
    END LOOP; 
END; 

然后,您可以通过v_var任何过程或函数。

+0

我想返回一个单一的字符串到Java调用这个存储过程。在那种情况下,我会通过遍历v的表来构建varchar2来构建返回的最终字符串吗? – haju

+0

是的,你可以做到这一点。 –

2

从注释看来,您似乎只是在寻找一种方便的方法将DBMS_OUTPUT缓冲区提取到Java应用程序中。尽管可以将SQL类型发布为与Java兼容的数组(我不是Java开发人员,但我会将其留给其他人 - 但请注意,dbms_output.get_lines已超载,并且可能会返回dbmsoutput_linesarray,这可能比使用dbms_output.chararray),我想到一个引用游标可能会做到这一点。

如果是这样,你可以创建一个返回的输出缓冲区作为集合函数:

create or replace function get_dbms_output 
    return dbmsoutput_linesarray 
as 
    l_output dbmsoutput_linesarray; 
    l_linecount number; 
begin 
    dbms_output.get_lines(l_output, l_linecount); 

    if l_output.count > l_linecount then 
     -- Remove the final empty line above l_linecount 
     l_output.trim; 
    end if; 

    return l_output; 
end get_dbms_output; 

现在,你可以发出一个正常的SQL查询作为

select column_value from table(get_dbms_output) 

这应该给你一个标准参考游标。

演示:

SQL> set serveroutput off 
SQL> 
SQL> begin 
    2  dbms_output.enable; 
    3  dbms_output.put_line('This is a line'); 
    4  dbms_output.put_line('This is another line'); 
    5  dbms_output.put_line('This is the last line.'); 
    6 end; 
    7/

PL/SQL procedure successfully completed. 

SQL> select column_value from table(get_dbms_output); 

COLUMN_VALUE 
-------------------------------------------------------- 
This is a line 
This is another line 
This is the last line. 

3 rows selected. 

(该set serveroutput off刚刚停止的SQL * Plus从在通话结束做自己的dbms_output.get_lines并留下我的功能无事可做的dbms_output.enable是因为set serveroutput off禁用DBMS_OUTPUT。 。这些仅用于SQL * Plus中的演示目的,您不需要Java中的任何一个。)

+0

对于column_value,变量类型是什么? – haju

+0

啊,好点 - 它是'varchar2(32767)',现在我想起它可能会给你一些超过4000字节的行的问题(除非你在Oracle 12c上,并且你已经[启用扩展数据类型]( https://oracle-base.com/articles/12c/extended-data-types-12cR1))。 –

+0

我刚刚测试了一个4001字符的行,并且它失败了'ORA-24920:列大小对于客户端来说太大了,尽管我怀疑如果客户端没有拒绝这个值,它仍然会失败。也许我可以让它成为一个流水线函数,让它检查每一行并在必要时分割它,所以它不会失败,但它可能会破坏一些格式并将一些单词分成两部分,除非我添加更多的逻辑。 –

相关问题