[英]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_PKG和JSON_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.