DBMS_OUTPUT buffer size (client or database side) - oracle

I use SQL Developer to run queries on Oracle databases, the DBMS_OUTPUT buffer size is set by default (20000) in SQL Developer.
When I run the query against DEV database, everything is OK.
When I run the same query against Production database, the same SQL Developer session, I get error :
ORA-20000: ORU-10027: buffer overflow, limit of 10000 bytes.
Have you an idea why ? There is any limitation set on database side.

You didn't reveal how exactly you call procedures from dbms_output package so I can just guess. In fact I got same error and found a cause in my case which might be of course different than yours.
In my case I had a buffer of length 10000 (in PLSQL Developer, which is not important here) and I called only the dbms_output.put procedure, not dbms_output.put_line. The put procedure keeps filling buffer and does not flush it, even if string argument contains newline character.
Compare these two attempts of writing 1001 lines of ten-characters-long string (nine visible + line terminator):
begin
dbms_output.enable(10000);
for i in 1..1001 loop
dbms_output.put('123456789' || chr(10)); -- fails here
end loop;
end;
vs.
begin
dbms_output.enable(10000);
for i in 1..1001 loop
dbms_output.put_line('123456789'); -- works
end loop;
end;
The first example fails with ORA-20000: ORU-10027: buffer overflow, limit of 10000 bytes because it tries to put 10010 chars into buffer.
(The real story from which this minimalistic example was synthetized was printing package source code from dba_source table. Every line of source source code in text column is terminated by newline character which must be trimmed before sending into put_line - without trimming it would be doubled; sending text into sole put method would cause the buffer trouble.)

Related

generating "large" files through dbms_output

... before anyone marks this as a duplicate ... i have checked Is there any way to flush output from PL/SQL in Oracle?
and am looking for more information on how to actually do what that answer referenced ... so hold it.
I absolutely need to use DBMS_OUTPUT due to various reasons. UTL_FILE won't help.
For the benefit of this question, let's say i'm generating a flat file.
declare
function printerFunction(someArray) <---- this function swallows an array and dumps it to
is begin
for each element of some array ... dbms_output.put_line(element)
end printerFunction;
begin
for row in some_cursor loop
printerFunction(someArrayData);
end loop;
end
The aforementioned code block is essentially the jist of the matter... nothing special.
Dave Costa mentions something along the lines of "break up a large PL/SQL block into multiple smaller blocks" ... the question is how.
I understand I have a nested loop structure and this is most likely the reason behind the output buffer not flushing itself, but can't think of a way to keep some_cursor open or for all intents and purposes switch back and forth between two code blocks outside of that loop .
dbms_output.enable(null) is kind of a dumb idea in this case as well. Ideally i'd like to essentially flush out the stuff in the buffer to my sqlDeveloper scriptOutput window and move on with processing at a specific rate ... say every 10000 rows or so. is this even possible? ... I mean... the main begin [pl/sql code] end structure is essentially a code block itself.
... the db I'm working on is a production environment, and i can only use a limited, read-only set of commands. ... in other words ... SYS stuff is beyond my reach.
As Dave Costa explains in the answer you link to, if you want the client to display the information before all your processing is done, you'd need to break your code up into separate blocks that you could send separately to the database. The client has no way to read the data out of the dbms_output buffer until the database returns control to the client.
You wouldn't realistically keep a single cursor open across these separate calls. You'd open a new cursor each time. For example, if you had a block
begin
for cursor in (select * from ... order by ... offset x fetch next y rows only)
loop
<<do something>>
end loop;
end;
you could have that run for 10,000 rows (or whatever value of y you want), get the output in SQL Developer, then run another block to process the next y rows (or have x and y be variables defined in SQL Developer that you update in each iteration or create a package to save state in package variables but I assume that is not an option here). But you'd need to submit a new PL/SQL block to the database for each set of y rows that you wanted to process. And this query will get less efficient as you try to get later and later pages since it has to sort more and more data to get the results.
Practically, it is pretty unlikely that you'd really want to break your logic up like this. You'd almost always be better off submitting a single PL/SQL block and letting the client fetch the data once at the end. But using dbms_output to generate a file is pretty weird in the first place. You'd generally be better served letting SQL Developer generate the file. For example, if you return a sys_refcursor for
select *
from table(someArrayData)
or just run whatever query that was used to generate someArrayData, SQL Developer can happily save that data into a CSV file, and XLS(X) file, etc.
You can clear the buffer by consuming the messages manually. This snippet puts something in the buffer and then clears it. My client shows no output.
DECLARE
var_status integer := 0;
var_dummy varchar2(32767);
BEGIN
dbms_output.put_line('this is a test');
WHILE var_status = 0
LOOP
DBMS_OUTPUT.GET_LINE (line => var_dummy,
status => var_status);
END LOOP;
END;

Reason for data inconsistency if UTL_FILE is not closed after writing data into the file in Oracle SQL

I am using Oracle SQL developer as a client for Oracle 11g DB. Its a simple issue. I am fetching data from a table and writing the data into a text file. This particular piece of code is scheduled as a monthly job and the output text file is placed in DB directory path.
The number of records differ each month. The text output file had correct number of rows as like in table till last month's job. This month, data inconsistency is observed in the text file. The number of rows to be exported to text file is lets say, 1000. The output file has total of 950 or so rows . The data do not match. This issue was not occurring till last month.
On testing further, observed, file was not closed after writing using UTL_FILE.FCLOSE(M_OUT_SYS). Issue is resolved after closing the file, data matches now.
But why the issue didn't surface till last month when program ran without file closure and why the issue surfaced suddenly in this month?
declare
M_OUT_SYS UTL_FILE.FILE_TYPE;
M_DATA VARCHAR2(2000);
M_DIRECTORY_NAME ALL_DIRECTORIES.DIRECTORY_NAME%TYPE;
M_DELIMITER_FILE_NAME VARCHAR2(250);
cursor c1 is
select * from example_table;
begin
M_DIRECTORY_NAME := 'OracleDB_dir_name';
M_DELIMITER_FILE_NAME := 'OutputTextFile.txt';
M_OUT_SYS := UTL_FILE.FOPEN(M_DIRECTORY_NAME,
M_DELIMITER_FILE_NAME,
'W', 8192);
UTL_FILE.PUT_LINE(M_OUT_SYS,'column1|column2|column3');
for i in c1 loop
M_DATA := I.column1 || '|' || I.column2 || '|' || I.column3;
UTL_FILE.PUT_LINE(M_OUT_SYS, M_DATA);
end loop;
end;
See the utl_file docs for 11.2 https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm :
UTL_FILE.PUT_LINE does not (by default) flush to the file after each call, it just writes to a buffer.
Flushing will happen after either:
The instance decides to flush due to reaching a certain buffer size (around 10KB)
Data is manually flushed with utl_file.fflush
The file handle is closed
The session disconnects (which is similar to 3)
My money would be on your previous jobs exited their session by the time you came to pick up the file. And when you noticed the difference it's because the session was still open and it had last triggered an auto flush on the 950th row.

How to "print" a variable without dbms_output and utl_file - Oracle

I'm on a remote server without privileges to create a directory and I have a clob column (a xml code) that I want to see. As I'm using a very old version of PL/SQL_developer (8.0.4) and I can't update to a new one, with a single "select X from T", I get "CLOB" as result. So, searching on the Internet I found this in the AskTOM and I try to use the plsql solution
declare
my_var varchar2(32000 char); --tried with long, didn't work too.
begin
for x in ( SELECT X from T)
loop
my_var := dbms_lob.substr( x.X, 32000, 1 );
dbms_output.put_line(my_var);
end loop;
end;
But when i try to run, I have "ORA-20000 ORU-10027 buffer overflow limit of 10000 bytes".
I try to increase the limit with DBMS_OUTPUT.ENABLE(32000); but got error too "ORA-06502: PL/SQL: numeric or value error: character string buffer too small", I only can decrease the limit of 10000.
I know I don't have the SET serveroutput ON, but when I tried to add this line, guess what, error: "ORA-00922: missing or invalid option" but if I put 4000 instead of 32000 it works, show the first 4000b of data, so, I don't need this line.
So, I can't print, since the variable is too big, and I can't write the text to a file, since I don't have privilegies, there is any other way to see that variable?

Stored Proc hitting ORA-06502: PL/SQL: numeric or value error

I'm having a problem calling a stored procedure from OSB 11g thru JCA Adapter.
The error I'm getting is:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 1
The error is as short as it is without any appends behind the error description. It only happens in production environment and there are no problems when I point the database to the UAT one.
More surprisingly, it will work in production envrionement if one of the variables I pass in is less than 128 characters. (or else I will hit the error above).
The stored procedure type and length are defined correctly. having the table column able to cope for 4000 characters.
Both Oracle 9i DB sharing the same major minor build revision. The stored proc is located in a package. I extracted out and compared the stored proc from both DB environments using winmerge and it shows they mirror each other.
Executing the stored procedure manually in production environment works, provides that I declare a big enough varchar size. I manage to simulate the ORA-06502 error by declaring a variable size lesser than the data length I'm passing in.
I even went as far as capturing the network dump from both executions and found there are slightly differences. (Note: I'm reusing the same datasource and only change the ip and username in WLS and did a restart before each executions)
When I point to production environment(the 1 having trouble), the tcpdump looks something like below:
BEGIN packagename.stored_proc_name(V_value1=>:1 , v_value2=>:2, v_value3=>:3); END .... {variable1}... {variable2}... {variable3})
When I point to UAT environment(the successful 1), the dump looks shorter and without the BEGIN; END tag
.... {variable1}... {variable2}... {variable3})
What else could have gone wrong? Appreciate for any helps!
"The stored proc is located in a package. I extracted out and compared the stored proc from both DB environments using winmerge and it shows
they mirror each other."
It is not about the code, the issue is data specific. In UAT you might not have production like data and thus you aren't able to replicate the issue.
Your error message just says error at line 1, which is not quite helpful. Are you executing the code without formatting it? If you format the code and execute it, and remove all exception handling, you will correctly know the line number. For example :
SQL> declare
2 num number;
3 begin
4 num := 'a';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
See, it clearly tells that error is at line 4.
By any chance if you have an EXCEPTION block, then make sure you use dbms_utility.format_error_stack and dbms_utility.format_error_backtrace to log the error details. Else, the error line number will be never correct.

The Pl/SQL Code doesn't give any output [duplicate]

This question already has an answer here:
Procedure not printing anything
(1 answer)
Closed 10 months ago.
I'm a beginner in PL/SQL Coding.
This is a test program.
Can you please tell the reason for no output.
Please guide me.
create or replace package menu as
procedure show(name varchar2);
end menu;
/
create or replace package body menu as
procedure show(name varchar2) AS
new_number number;
begin
select count(*) into new_number from stock;
dbms_output.put_line('This is output.');
end;
end menu;
/
You need to set Oracle to output lines to the console manually:
set serveroutput on;
This should be the first line in your code.
As others have said, SQL*Plus will only get the output from DBMS_OUTPUT if you first SET SERVEROUT ON.
Your code merely compiles and stores a database package on the database; you haven't actually run it. To run it you'd execute something like this:
BEGIN menu.show('something'); END;
/
Please read the docs
Operational Notes
If you do not call GET_LINE, or if you do not display the messages on your screen in SQL*Plus, the buffered messages are ignored.
SQL*Plus calls GET_LINES after issuing a SQL statement or anonymous PL/SQL calls.
Typing SET SERVEROUTPUT ON in SQL*Plus has the effect of invoking
DBMS_OUTPUT.ENABLE (buffer_size => NULL);
with no limit on the output.
You should generally avoid having application code invoke either the DISABLE Procedure or ENABLE Procedure because this could subvert the attempt of an external tool like SQL*Plus to control whether or not to display output.
Note:
Messages sent using DBMS_OUTPUT are not actually sent until the sending subprogram or trigger completes. There is no mechanism to flush output during the execution of a procedure.
Exceptions
DBMS_OUTPUT subprograms raise the application error ORA-20000, and the output procedures can return the following errors:
Table 68-1 DBMS_OUTPUT Errors
Error Description
ORU-10027: Buffer overflow
ORU-10028: Line length overflow
Rules and Limits
The maximum line size is 32767 bytes.
The default buffer size is 20000 bytes. The minimum size is 2000 bytes and the maximum is unlimited.
So SET SERVEROUTPUT ON is only for SQL*Plus.

Resources