The problem
If you need to see (some restore point) state of v$database data, then you probably might use query like:select * from v$database;Problem is bad readability of such an output:
And here is where print_record comes at it's best.
This is v1.1 thanks to Marko Sutic and his comments with url to original postings. In fact this code come originally from Tom's Kyte page - print_table procedure. Mine part is small adding at the begginig to store session parameters.
I was not aware of that before so now I do appologize for this to all authors ...
Implementation
Implementation is more then easy-install the procedure. In my case it is part of tools package but it can be standalone as well:procedure print_record ( p_query in varchar2 ) is /* these two constants manage output formatting for strings. adjust them as you wish. */ c_text_seg_len CONSTANT NUMBER := 80; -- do not exceed 224 c_cont_char CONSTANT VARCHAR2(30) := '~'; -- for continuation cur_da_cursor INTEGER DEFAULT dbms_sql.open_cursor; l_column_value VARCHAR2(4000); l_column_title VARCHAR(30); l_status INTEGER; l_table_desc dbms_sql.desc_tab; l_column_count NUMBER; l_nls_date VARCHAR2(32); begin select value into l_nls_date from nls_session_parameters where parameter = 'nls_date_format'; execute immediate 'alter session set nls_date_format=''dd-mon-yyyy hh24:mi:ss'' '; dbms_sql.parse(cur_da_cursor,p_query,dbms_sql.native); dbms_sql.describe_columns (cur_da_cursor,l_column_count,l_table_desc); for i in 1 .. l_column_count loop dbms_sql.define_column (cur_da_cursor,i,l_column_value,4000); end loop; l_status := dbms_sql.execute(cur_da_cursor); while (dbms_sql.fetch_rows(cur_da_cursor) > 0) loop for i in 1 .. l_column_count loop dbms_sql.column_value (cur_da_cursor,i,l_column_value); if l_table_desc(i).col_type = 1 then if length(l_column_value) > 0 then l_column_title := rpad(l_table_desc(i).col_name, 30); for j in 1 .. ceil(length(l_column_value)/c_text_seg_len) loop dbms_output.put_line(l_column_title || ': ' || substr(l_column_value, (((j-1)*c_text_seg_len)+1), c_text_seg_len) ); l_column_title := rpad(c_cont_char, 30); end loop; else dbms_output.put_line (rpad( l_table_desc(i).col_name, 30) || ': ' || l_column_value); end if; elsif l_table_desc(i).col_type in (8, 23, 24, 112, 113, 114, 115) then dbms_output.put_line (rpad(l_table_desc(i).col_name, 30 ) || ': ** UNPRINTABLE **'); else dbms_output.put_line (rpad( l_table_desc(i).col_name, 30) || ': ' || l_column_value ); end if; end loop; dbms_output.put_line( '--------------------------------------------------------------------' ); end loop; execute immediate 'alter session set nls_date_format='''||l_nls_date||''''; exception when others then begin dbms_output.put_line(sqlerrm); dbms_output.put_line (chr(9)); dbms_output.put_line (p_query); exception when others then null; end; execute immediate 'alter session set nls_date_format='''||l_nls_date||''''; end print_record;
"print_record" in action
If you run the same query as before "through" print_records:exec tools.print_record('select * from v$database');Result looks like:
And here is another enchantment for columns that are longer then 255 chars. Output is devided into several columns where length is defined with c_text_seg_len constant.
For the end
As you can see the main idea to keep easiness is full filled-you can use the same query in both cases!Remember that every record will produce one set of rows....regardless how many they are in result.
Cheers!
Hi Damir,
ReplyDeletebest tool for daily tasks, troubleshooting, etc... is sqlplus which I use a lot. So it is important for me to have output nicely formatted.
I'm using print_table from Tom Kyte http://bit.ly/5h7FXg for formatting output.
But your procedure does the same thing and it is very useful.
Best regards,
Marko
Marko,
ReplyDeleteThank you for pointing me this information.
As you see I have modified blog and mention all information that you have provided to me. Hope now is more fair...
Cheers!