如何将Oracle PL/SQL动态查询结果以表格形式展示
解决方案
一、已知字段列表的场景(适配你实际10个字段的需求)
直接固定每个字段的显示宽度,先输出表头、分隔线,再循环格式化每行数据,确保对齐规整:
修改后的代码示例:
set serveroutput on size 1000000 declare TYPE EmpCurTyp IS REF CURSOR; v_emp_cursor EmpCurTyp; var1 varchar2(1000) := 'select document_id, payment_amount, report_date from blu_payment_report_history'; var2 varchar(100) := ' where rownum <=3 '; finalvar varchar2(2000); -- 扩大变量长度,避免动态SQL拼接后截断 -- 按实际10个字段定义对应变量,这里以3个字段为例示范 v_document_id blu_payment_report_history.document_id%TYPE; v_payment_amount blu_payment_report_history.payment_amount%TYPE; v_report_date blu_payment_report_history.report_date%TYPE; -- 定义各列显示宽度,按需调整 c_col1_width constant number := 15; c_col2_width constant number := 18; c_col3_width constant number := 20; begin finalvar := var1 || ' ' || var2; OPEN v_emp_cursor FOR finalvar; -- 打印表头 dbms_output.put_line( rpad('DOCUMENT_ID', c_col1_width) || '|' || rpad('PAYMENT_AMOUNT', c_col2_width) || '|' || rpad('REPORT_DATE', c_col3_width) ); -- 打印分隔线 dbms_output.put_line( rpad('-', c_col1_width, '-') || '+' || rpad('-', c_col2_width, '-') || '+' || rpad('-', c_col3_width, '-') ); LOOP FETCH v_emp_cursor INTO v_document_id, v_payment_amount, v_report_date; EXIT WHEN v_emp_cursor%NOTFOUND; -- 格式化每行数据:字符型左对齐,数值型右对齐更美观 dbms_output.put_line( rpad(nvl(v_document_id, ''), c_col1_width) || '|' || lpad(nvl(to_char(v_payment_amount, '999,999.00'), ''), c_col2_width) || '|' || rpad(nvl(to_char(v_report_date, 'YYYY-MM-DD HH24:MI:SS'), ''), c_col3_width) ); END LOOP; CLOSE v_emp_cursor; end; /
关键细节:
- 扩大
finalvar的长度,避免动态SQL拼接后因长度不足被截断; - 使用
rpad()(左对齐填充)和lpad()(右对齐填充)固定列宽,保证每行对齐; - 用
nvl()处理空值,避免空字段导致的格式混乱; - 按实际10个字段扩展变量定义和列宽设置即可。
二、动态查询(未知字段数量/名称)的通用场景
如果你的动态查询字段不固定,可以用DBMS_SQL包自动获取列元数据,生成适配的表格输出:
set serveroutput on size 1000000 declare v_cursor_id integer; v_col_count integer; v_col_desc dbms_sql.desc_tab; v_sql varchar2(2000); v_value varchar2(4000); c_default_width constant number := 20; -- 默认列宽,可按需调整 begin -- 拼接动态SQL v_sql := 'select document_id, payment_amount, report_date from blu_payment_report_history where rownum <=3'; -- 初始化DBMS_SQL游标 v_cursor_id := dbms_sql.open_cursor; dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native); dbms_sql.describe_columns(v_cursor_id, v_col_count, v_col_desc); -- 绑定列变量 for i in 1..v_col_count loop dbms_sql.define_column(v_cursor_id, i, v_value, 4000); end loop; -- 执行查询 dbms_sql.execute(v_cursor_id); -- 打印表头 for i in 1..v_col_count loop dbms_output.put(rpad(upper(v_col_desc(i).col_name), c_default_width) || '|'); end loop; dbms_output.new_line; -- 打印分隔线 for i in 1..v_col_count loop dbms_output.put(rpad('-', c_default_width, '-') || '+'); end loop; dbms_output.new_line; -- 循环获取并格式化打印数据 while dbms_sql.fetch_rows(v_cursor_id) > 0 loop for i in 1..v_col_count loop dbms_sql.column_value(v_cursor_id, i, v_value); dbms_output.put(rpad(nvl(v_value, ''), c_default_width) || '|'); end loop; dbms_output.new_line; end loop; dbms_sql.close_cursor(v_cursor_id); end; /
关键细节:
- 用
dbms_sql.describe_columns自动获取查询的列数量和名称,无需手动定义表头; - 统一使用默认列宽,也可根据列类型/长度动态调整宽度;
- 所有字段转成字符串输出,适配不确定字段类型的场景。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

