Is dbms_output.put() being buffered differently fr

2019-02-24 00:15发布

问题:

Im using Aqua Data Studio to debug a stored proc by scattering output statments throughout.

I have a delete statement in the package which violate an integrity constraint:

DELETE FROM x WHERE x.ID = an_x_with_children;

My proc fails with an ORA-02292 on this line, as expected. I want to see the value of the an_x_with_children variable. So I wrap the line with outputs like so:

dbms_output.put('Attempting to delete x: ' || an_x_with_children);
DELETE FROM x WHERE x.ID = an_x_with_children;
dbms_output.put(' Success');

And expect to see the message as the last thing in the messages console prior to the integrity constraint violated error message. But it doesn't print!

Now if I change the output to use the put_line() procedure like this:

dbms_output.put_line('Attempting to delete x: ' || an_x_with_children);
DELETE FROM x WHERE x.ID = an_x_with_children;
dbms_output.put_line(' Success');

I see the message "Attempting to delete x: 123" immediately before the proc errors out.

The docs for the dbms_output package don't mention the put and put_line procedures behaving any differently in this respect. For instance, it says

Output that you create using PUT or PUT_LINE is buffered.

So I would expect either both or neither to show output when the proc errors.

Can someone explain what's going on with this behaviour to me?

回答1:

Here is an example that shows the behaviour you're seeing:

SQL> exec dbms_output.put_line('hello')
hello

PL/SQL procedure successfully completed.

SQL> exec dbms_output.put('hello again')

PL/SQL procedure successfully completed.

SQL> exec dbms_output.put(' and again')

PL/SQL procedure successfully completed.

SQL> exec dbms_output.new_line
hello again and again

PL/SQL procedure successfully completed.

The documentation says "SQL*Plus calls GET_LINES after issuing a SQL statement or anonymous PL/SQL calls."

And procedure GET_LINES says "This procedure retrieves an array of lines from the buffer."

With PUT you haven't completed your line yet. And so it doesn't print.

The NEW_LINE procedure mentions this as well: "This procedure puts an end-of-line marker. The GET_LINE Procedure and the GET_LINES Procedure return "lines" as delimited by "newlines". Every call to the PUT_LINE Procedure or NEW_LINE Procedure generates a line that is returned by GET_LINE(S)."

Regards,
Rob.