dbms_utility.format_error_stack 在行后换行

问题描述 投票:0回答:2

我目前正在 Oracle SQL Developer 中处理 PL SQL 脚本,我在其中还添加了一些 dbms_output 命令用于日志记录。下面的代码工作得很好,我唯一的问题是在两行(format_error_stack 和 format_error_backtrace)之后插入了一个换行符,我想阻止它。下面的程序只是一个测试程序,不应产生任何有价值的输出。

procedure test(
    i_key in number
)
is
    l_test  number := 0;
begin

    dbms_output.put_line('TEST - START PROCEDURE');
    l_test := i_key;
    dbms_output.put_line('TEST - Value: ' ||i_key|| '.');
    raise no_data_found;
    
    exception
    when no_data_found then
        dbms_output.put_line('Exception: ' ||SUBSTR(DBMS_UTILITY.format_error_stack,1,4000));
        dbms_output.put_line('Backtrace: ' ||SUBSTR(DBMS_UTILITY.format_error_backtrace,1,4000));
        dbms_output.put_line('Test');
end;

上面的程序有以下输出:

TEST - START PROCEDURE
TEST - Value: 1.
Exception: ORA-01403: no data found

Backtrace: ORA-06512: at "EXAMPLE.TEST_PROC", line 19

Test


PL/SQL procedure successfully completed.

我已经用谷歌搜索了这个问题以及 DBMS_UTILITY 函数,但找不到任何合理的解释为什么在两个 DBMS_UTILITY 函数之后有换行符。

plsql oracle-sqldeveloper
2个回答
0
投票

看起来是关于线的长度(不过,那是相当的线)。

见第 16 行,它提取长度为 25 个字符的子字符串并导致“换行”:

SQL> create or replace
  2  procedure test(
  3      i_key in number
  4  )
  5  is
  6      l_test  number := 0;
  7  begin
  8
  9      dbms_output.put_line('TEST - START PROCEDURE');
 10      l_test := i_key;
 11      dbms_output.put_line('TEST - Value: ' ||i_key|| '.');
 12      raise no_data_found;
 13
 14      exception
 15      when no_data_found then
 16          dbms_output.put_line('Exception: ' ||SUBSTR(DBMS_UTILITY.format_error_stack,1,25));                  --> here
 17          dbms_output.put_line('Backtrace: ' ||SUBSTR(DBMS_UTILITY.format_error_backtrace,1,4000));
 18          dbms_output.put_line('Test');
 19  end;
 20  /

Procedure created.

SQL> set serveroutput on
SQL> exec test (1);
TEST - START PROCEDURE
TEST - Value: 1.
Exception: ORA-01403: no data found
                                                             --> here
Backtrace: ORA-06512: at "SCOTT.TEST", line 11

Test

PL/SQL procedure successfully completed.

但是,如果将其缩短为 24 个字符,则不再有换行符:

SQL> create or replace
  2  procedure test(
  3      i_key in number
  4  )
  5  is
  6      l_test  number := 0;
  7  begin
  8
  9      dbms_output.put_line('TEST - START PROCEDURE');
 10      l_test := i_key;
 11      dbms_output.put_line('TEST - Value: ' ||i_key|| '.');
 12      raise no_data_found;
 13
 14      exception
 15      when no_data_found then
 16          dbms_output.put_line('Exception: ' ||SUBSTR(DBMS_UTILITY.format_error_stack,1,24));                 --> here
 17          dbms_output.put_line('Backtrace: ' ||SUBSTR(DBMS_UTILITY.format_error_backtrace,1,4000));
 18          dbms_output.put_line('Test');
 19  end;
 20  /

Procedure created.

SQL> exec test (1);
TEST - START PROCEDURE
TEST - Value: 1.
Exception: ORA-01403: no data found                         --> here
Backtrace: ORA-06512: at "SCOTT.TEST", line 11

Test

PL/SQL procedure successfully completed.

SQL>

例如

SET LINESIZE 500
(在 SQL*Plus 中)有帮助吗?不。

为什么会这样?不知道。


0
投票

格式化的堆栈和回溯都以换行符结尾。

LENGTH(SUBSTR(DBMS_UTILITY.format_error_stack,1,4000)))
返回 25.

ASCII(SUBSTR(DBMS_UTILITY.format_error_stack,25,1)))
返回 10 - 这是换行符的字符代码。

然后你做

dbms_output.put_line(...)
也添加换行符

当您调用 PUT_LINE 时,您指定的项目后面会自动跟上一个行尾标记。如果调用 PUT 来构建一行,则必须通过调用 NEW_LINE 添加自己的行尾标记。 GET_LINE 和 GET_LINES 不返回未以换行符终止的行。

您可以通过使用

put
来避免这种情况,并且依赖消息总是以换行符结尾。但是当您将原始值截断为 4000 个字符时,您可能会有更长的回溯并且如果关闭则切断 - 然后不要以换行符结尾,因为它可能(或可能)在中间一条消息,而不是结束。您可以倒数到最后一个换行符,但这有点混乱。

有趣的是 backtrace 的文档包括一次打印一行的示例代码,它在换行符处拆分源文本,然后使用

put_line
添加一个。这将允许处理特别大的字符串,尝试直接传递到
put_line
可能会出错,因为它超过了可以处理的 limits - 即如果回溯超过 32k.

所以你可能想采用这种方法而不是只捕获前 4000 个字符。

© www.soinside.com 2019 - 2024. All rights reserved.