簡體   English   中英

Oracle PL/SQL 中的漂亮打印

[英]Pretty print in Oracle PL/SQL

在 Oracle PL/SQL 中是否有更好的方法打印到 STDOUT?

DBMS_OUTPUT.PUT_LINE 看起來非常基本和粗糙。 應該有類似 Python 的 pprint (Pretty Print) 之類的東西嗎?

PL/SQL旨在處理數據,而不是顯示數據,或者與調用它的客戶端交互(例如,因此沒有用戶輸入的機制)。

DBMS_OUTPUT“使您能夠從存儲過程和包發送消息。該包對於顯示 PL/SQL 調試信息特別有用”。 它不是為“漂亮”輸出而設計的,因為 PL/SQL 不是為那種工作而設計的。 並且重要的是要意識到調用您的過程的客戶端可能不會查看或顯示 DBMS_OUTPUT 緩沖區,因此您寫入的內容可能會丟失。

PL/SQL 不向標准輸出打印任何內容 DBMS_OUTPUT 調用寫入緩沖區 - 如果它完全被啟用 - 然后一旦 PL/SQL 完成執行,客戶端可以讀取該緩沖區並在某處顯示內容(如果它已啟用,同樣如此)。 這也意味着你不能用它來跟蹤進度,因為你在執行過程中看不到任何東西,只有當它完成時; 所以即使是調試,它也不總是最好的工具。

根據您要嘗試執行的操作,您可以通過set serveroutput on format wrapped上執行set serveroutput on format wrapped來使 SQL*Plus 中的內容看起來稍微好一點,這會阻止它在緩沖區行的開頭丟失空格。 但這通常是一個小好處。

更一般地說,您的過程應該通過 OUT 參數將其處理結果傳遞給調用者,或者使其成為返回有用信息的函數。

如果您當前正在嘗試使用dbms_output.put_line顯示查詢結果,那么這不是一個好主意。 您可以改為將集合或引用游標返回給客戶端,並讓客戶端擔心如何顯示它。 您可以使用綁定變量在 SQL*Plus 或 SQL Developer 中輕松顯示引用游標。

夠漂亮嗎?

 --Pretty print
CREATE OR REPLACE PROCEDURE PP(input varchar2, p_pn varchar2:='PP')
AS
   pos   INTEGER;
   len   INTEGER      := 4000;
   nl    VARCHAR2 (2) := CHR (10);
   r_    VARCHAR2 (2) := CHR (13);
   v_padded varchar2(64):=p_pn;--rpad(p_pn, 5, ' ');
BEGIN
   IF LENGTH (input) > len
   THEN
      pos := INSTR (input, nl, 1, 1);
      IF pos > 0 AND pos < len
      THEN
         DBMS_OUTPUT.put_line (v_padded||': '||REPLACE (SUBSTR (input, 1, pos - 1), r_, ''));
         pp (SUBSTR (input, pos + 1),p_pn);
      ELSE
         IF pos = 0 AND LENGTH (input) <= len
         THEN
  DBMS_OUTPUT.put_line (v_padded||': '||REPLACE (SUBSTR (input, 1, len), r_, ''));
         ELSE
  DBMS_OUTPUT.put_line (v_padded||': '||REPLACE (SUBSTR (input, 1, len), r_, ''));
  pp (SUBSTR (input, len + 1),p_pn);
         END IF;
      END IF;
   ELSE
      DBMS_OUTPUT.put_line (v_padded||': '||REPLACE (SUBSTR (input, 1, len), r_, ''));
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      RAISE;
END PP;

示例輸出:

SQL>
FUN_ENCRYPT_PERSON_ID: Input  = 123456789123
FUN_ENCRYPT_PERSON_ID: Suffix = 123
FUN_ENCRYPT_PERSON_ID: Base   = 876543210
FUN_ENCRYPT_PERSON_ID: 2->5 1 10000     10000
FUN_ENCRYPT_PERSON_ID: 3->9 2 200000000 200010000
FUN_ENCRYPT_PERSON_ID: 4->2 3 30        200010030
FUN_ENCRYPT_PERSON_ID: 5->1 4 4         200010034
FUN_ENCRYPT_PERSON_ID: 6->3 5 500       200010534
FUN_ENCRYPT_PERSON_ID: 7->6 6 600000    200610534
FUN_ENCRYPT_PERSON_ID: 8->4 7 7000      200617534
FUN_ENCRYPT_PERSON_ID: 9->8 8 80000000  280617534
FUN_ENCRYPT_PERSON_ID: Output = 280617534123

沒有我知道的內置函數。 但是我編寫了一個過程來從存儲過程中漂亮地打印結果集。

該過程稱為print_out_resultset。 用法示例:

....
cursor mycur (mynum in number) is
select * from mytable where mycol >= mynum; 

myrow mytable%rowtype;
myvar number;
...
begin
....

print_out_resultset(query_string =>
  'select * from mytable where mycol >= :b1',
  col1 => 'SAM', col2 => 'FRED', col3 => 'ERIC',
  b1 => myvar,
  maxrows => 4);

open mycur(myvar);
fetch mycur into myrow;
while mycur%found loop
....

示例結果

SQL> set serverout on;
SQL> execute myproc;
SAM         FRED        ERIC       
-----------------------------------
32A         49B         15C
34A         11B         99C
11F         99A         887
77E         88J         976

代碼在這里: http : //toolkit.rdbms-insight.com/print_out_resultset.php

多年前,我僅將其用於故障排除; 當然,在部署到生產之前進行測試

實際上有一種標准方法,但它僅適用於 varchar 變量:

declare
  v_str varchar2(100):= 'formatted';
  v_int int := 10 ;
begin
  dbms_output.put_line(
     UTL_LMS.FORMAT_MESSAGE('Somebody told that "%s" output works well with ' 
                            ||'varchar variables, but not with int variables: "%d". '
                            ||'Only with constant integers (%d) it works.'
                            , v_str, v_int, 100)                            
  );
end;

如果您正在嘗試打印 json 對象,則有一種使用JSON_UTIL_PKGJSON_PRINTER進行打印的更好方法。

  L_JSON_LIST         JSON_LIST;
  L_JSON              JSON;
  L_CLOB              CLOB;
BEGIN
  --JSON_UTIL_PKG.SQL_TO_JSON returns a list, so storing it in a JSON_LIST.
  L_JSON_LIST := JSON_UTIL_PKG.SQL_TO_JSON('SELECT
                                      ''abc'' "Address1",
                                      ''def'' "Address2",
                                      ''gh'' "City"
                                     FROM
                                       DUAL');
  DBMS_LOB.CREATETEMPORARY(L_CLOB, TRUE);                            
  --get the first item in the list
  L_JSON :=       JSON(L_JSON_LIST.GET(1));
  --It takes a json object and will return it in a clob.
  JSON_PRINTER.PRETTY_PRINT(OBJ => L_JSON, BUF => L_CLOB); 

  --output  
  DBMS_OUTPUT.PUT_LINE(L_CLOB);                                    
END;

並且,輸出如下所示,

{
  "Address1" : "abc"
,
  "Address2" : "def"
,
  "City" : "gh"

}

也許您正在尋找 fnd_file 函數

fnd_file.put_line(fnd_file.output,:message);

其中 :message 是您要打印的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM