SQL ORACLE converting table to the html code - sql

I'm working on oracle and taking report from database Oracle.
SELECT OPERATION, OBJECT_TYPE, CPU_COST, IO_COST FROM SYS.V_$SQL_PLAN;
I want to send this report with html formate in mail body to the Database Admin.
Is there any way to do this in pl-sql in oracle?

Yes this is possible you need:
a) PL/SQL procedure to create the body html out of the SQL
b) PL/SQL procedure to send the body html in an html email to the admin
For a) here you can write a custom procedure which creates the html out of the sql cursor
for cur in (select * from query) loop
html := html || '<tr>';
html := html || '<td>';
html := html || cur.col1;
html := html || '</td>';
html := html || '<td>';
html := html || cur.col2;
html := html || '</td>';
...
html := html || '<td>';
html := html || cur.coln;
html := html || '</td>';
html := html || '</tr>';
or search/write some generic code like https://aykutakin.wordpress.com/2013/06/18/create-html-table-from-oracle-table-in-plsql/
For b) Use UTL_SMTP

Use all steps mentioned in attached screenshot, in case of any problem let me know to help you.
Here instead of col 1 you can define col 2, col 3 .... And so on, with one open td and one close td in similar way.
Make sure data count is not more then 10000. Else during browser load it will hang.

Related

How to use db directory in XMLDOM subset type

As i define note.dtd file in note_dtd_path and point it as &note_dtd_path with SYSTEM identifier, i can get the results what i want
SQL>
define note_dtd_path = "/home/oracle21c/SQL/note.dtd";
declare
doc dbms_xmldom.DOMDocument;
dt dbms_xmldom.DOMDOCUMENTTYPE;
n dbms_xmldom.DOMNode;
begin
doc := dbms_xmldom.newDomDocument('<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "&note_dtd_path">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body></body>
</note>
');
dt := dbms_xmldom.getDoctype(doc);
dbms_output.put_line ('docType name : ' || dbms_xmldom.getname(dt));
n := dbms_xmldom.makeNode(dt);
dbms_output.put_line('systemID : ' || dbms_xmldom.getsystemid(dt));
dbms_xmldom.freeDocument(doc);
end;
/
docType name : note
systemID : /home/oracle21c/SQL/note.dtd
PSM completed.
But, as i created directory in SQLPLUS tool and tried to point the file in right direction, it failed.
SQL> create or replace directory DIR288571 as "/home/oracle21c/SQL";
grant read, write on directory DIR288571 to tibero;
declare
doc dbms_xmldom.DOMDocument;
dt dbms_xmldom.DOMDOCUMENTTYPE;
n dbms_xmldom.DOMNode;
begin
doc := dbms_xmldom.newDomDocument('<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "$DIR288571/note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body></body>
</note>
');
dt := dbms_xmldom.getDoctype(doc);
dbms_output.put_line ('docType name : ' || dbms_xmldom.getname(dt));
n := dbms_xmldom.makeNode(dt);
dbms_output.put_line('systemID : ' || dbms_xmldom.getsystemid(dt));
dbms_xmldom.freeDocument(doc);
end;
/
**declare
*
ERROR at line 1:your text
ORA-31001: Invalid resource handle or path name "/$DIR288571/note.dtd"
ORA-06512: at "XDB.DBMS_XMLDOM", line 4703
ORA-06512: at "XDB.DBMS_XMLDOM", line 4721
ORA-06512: at line 16
**
**
is there any good method that i can get same results like using define options on the top by using create directory option `**

Oracle APEX - Download hidden SQL query into CSV

I am trying to create a button on a page in my application that will download the full table I am referencing as a CSV file. I cannot use interactive reports > actions > download CSV because the interactive reports have hidden columns. I need all columns to populate in the CSV file.
Is there a way to create a SQL Script and reference it in the button?
I have already tried the steps referenced in this link: Oracle APEX - Export a query into CSV using a button but it does not help as my queries will contain columns that are hidden in the Interactive Report.
Welcome to StackOverflow!
One flexible option would be to use an application process, to be defined in the shared components (process point = ajax callback).
Something like this:
declare
lClob clob;
lBlob blob;
lFilename varchar2(250) := 'filename.csv';
begin
lClob := UNISTR('\FEFF'); -- was necessary for us to be able to use the files in MS Excel
lClob := lClob || 'Tablespace Name;Table Name;Number of Rows' || utl_tcp.CRLF;
for c in (select tablespace_name, table_name, num_rows from user_tables where rownum <= 5)
loop
lClob := lClob || c.tablespace_name || ';' || c.table_name || ';' || c.num_rows || utl_tcp.CRLF;
end loop;
lBlob := fClobToBlob(lClob);
sys.htp.init;
sys.owa_util.mime_header('text/csv', false);
sys.htp.p('Conent-length: ' || dbms_lob.getlength(lBlob));
sys.htp.p('Content-Disposition: attachment; filename = "' || lFilename || '"');
sys.htp.p('Cache-Control: no-cache, no-store, must-revalidate');
sys.htp.p('Pragma: no-cache');
sys.htp.p('Expires: 0');
sys.owa_util.http_header_close;
sys.wpg_docload.download_file(lBlob);
end;
This is the function fClobToBlob:
create function fClobToBlob(aClob CLOB) RETURN BLOB IS
tgt_blob BLOB;
amount INTEGER := DBMS_LOB.lobmaxsize;
dest_offset INTEGER := 1;
src_offset INTEGER := 1;
blob_csid INTEGER := nls_charset_id('UTF8');
lang_context INTEGER := DBMS_LOB.default_lang_ctx;
warning INTEGER := 0;
begin
if aClob is null then
return null;
end if;
DBMS_LOB.CreateTemporary(tgt_blob, true);
DBMS_LOB.ConvertToBlob(tgt_blob, aClob, amount, dest_offset, src_offset, blob_csid, lang_context, warning);
return tgt_blob;
end fClobToBlob;
On the page, you need to set your button action to "Redirect to Page in this Application", the target Page to "0". Under "Advanced", set Request to "APPLICATION_PROCESS=downloadCSV", where downloadCSV is the name of your application process.
If you need to parameterize your process, you can do this by accessing page items or application items in your application process.
Generating the CSV data can be cumbersome, but there are several packages out there that make it easier. The alexandria packages are one of them:
https://github.com/mortenbra/alexandria-plsql-utils
An example on how to use the CSV Package is here:
https://github.com/mortenbra/alexandria-plsql-utils/blob/master/demos/csv_util_pkg_demo.sql

Writing output of query to .xlsx from a stored procedure in SQL Developer

I am needing to replace my current process of creating procedures in SQL Developer to write the output of a query into a CSV, with code that will output a .xlsx file instead. I've done some cursory research on the topic, but answers seem way over my head.
I've tried to mimic solutions I found on google/stack overflow to no avail.
EXAMPLE OF CSV PROCEDURE:
create or replace PROCEDURE EXAMPLE_FILE_CSV AS
CURSOR c_data IS
‘QUERY HERE’;
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN(location => 'EXTRACT_DIR',
filename => 'EXAMPLE_FILE.CSV',
open_mode => 'w',
max_linesize => 32767);
FOR cur_rec IN c_data LOOP
UTL_FILE.PUT_LINE(v_file,
cur_rec.COL1 || ',' ||
cur_rec.COL2 || ',' ||
cur_rec.COL3 || ',' ||
cur_rec.COL4 || ',' ||
cur_rec.COL5 || ',' ||
cur_rec.COL6 ;
END LOOP;
UTL_FILE.FCLOSE(v_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(v_file);
RAISE;
END;
Th example code you provided uses UTL_FILE, which can only access/create files on the Oracle server.
Since you mention you are currently manually running queries then copy/past(?) into Excel, the UTL_FILE option wont help you.
Now, to put this query data into a local/client side files this approach might get you started - write a script that runs in SQLPlus/SQLDeveloper and output a CSV file, using the following as a template/example. XLSX format is trickier.
myscript.sql:
SET LINES 2000
SET PAGES 0
SET TRIMSPOOL ON
SPOOL the_output.csv
SELECT col1 || ',' ||
col2 || ',' ||
col3 || ',' ||
col4 || ',' ||
col5 || ',' ||
col6
FROM the_table
WHERE ...;
SPOOL OFF
Another option you have is to use DBMS_OUTPUT.PUT_LINE as follows:
create or replace PROCEDURE EXAMPLE_FILE_CSV AS
CURSOR c_data IS
SELECT col1,
col2,
col3,
col4,
col5,
col6
FROM the_table
WHERE ...;
BEGIN
FOR cur_rec IN c_data LOOP
DMBS_OUTPUT.PUT_LINE(
cur_rec.COL1 || ',' ||
cur_rec.COL2 || ',' ||
cur_rec.COL3 || ',' ||
cur_rec.COL4 || ',' ||
cur_rec.COL5 || ',' ||
cur_rec.COL6 ;
END LOOP;
END;
/
To invoke this you would do the following in a caller script:
SET SERVEROUTPUT ON
SET VERIFY OFF
SET LINES 2000
SET TRIMSPOOL OFF
SPOOL the_output.csv
EXEC EXAMPLE_FILE_CSV;
SPOOL OFF;
the mentioned requirement is feasible by using 'xls' coding via plsql.
in simple words- we use plsql to generate xls coding as per need and have it as a excel file.
the basic xls coding to generate an excel file:
<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Sheet1">
<Table>
<Row>
<Cell><Data ss:Type="String">cell data</Data></Cell>
.........
</Row>
........
</Table>
</Worksheet>
......
</Workbook>
the approach is to generate the coding with the values from the database accordingly.
example:
consider the table:
ROLL_NO NAME AGE
01 student no 1 15
following plsql code will generate the excel sheet for this table record
declare
cursor c1 is select * from student_tbl;
l_xls_code varchar2(4000);
begin
l_xls_code:= CHR(60)||'?xml version='||CHR(34)||'1.0'||CHR(34)||'?'||CHR(62)||CHR(12)||
CHR(60)||'Workbook xmlns='||CHR(34)||'urn:schemas-microsoft-com:office:spreadsheet'||CHR(34)||'
xmlns:o='||CHR(34)||'urn:schemas-microsoft-com:office:office'||CHR(34)||'
xmlns:x='||CHR(34)||'urn:schemas-microsoft-com:office:excel'||CHR(34)||'
xmlns:ss='||CHR(34)||'urn:schemas-microsoft-com:office:spreadsheet'||CHR(34)||'
xmlns:html='||CHR(34)||'http://www.w3.org/TR/REC-html40'||CHR(34)|| CHR(62) ||
CHR(60)||'Worksheet ss:Name='||CHR(34)||'Student Data'||CHR(34)|| CHR(62) ||
CHR(60)||'Table'|| CHR(62)||
CHR(60)||'Row'|| CHR(62)||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||'Roll No.'||CHR(60)||'/Data'|| CHR(62)|| CHR(60)||'/Cell'|| CHR(62) ||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||'Name'||CHR(60)||'/Data'|| CHR(62)||CHR(60)||'/Cell'|| CHR(62) ||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||'Age'||CHR(60)||'/Data'|| CHR(62)||CHR(60)||'/Cell'||CHR(62) ||
CHR(60) ||'/Row'|| CHR(62);
-- dynamically having values from the table into the excel sheet
For rec in c1
loop
l_xls_code:= l_xls_code||
CHR(60)||'Row'|| CHR(62)||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||rec.roll_no||CHR(60)||'/Data'|| CHR(62)|| CHR(60)||'/Cell'|| CHR(62) ||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||rec.name||CHR(60)||'/Data'|| CHR(62)||CHR(60)||'/Cell'|| CHR(62) ||
CHR(60)||'Cell'|| CHR(62)||CHR(60)||'Data ss:Type='||CHR(34)||'String'||CHR(34)|| CHR(62)||rec.age||CHR(60)||'/Data'|| CHR(62)||CHR(60)||'/Cell'||CHR(62) ||
CHR(60) ||'/Row'|| CHR(62);
end loop;
l_xls_code:= l_xls_code|| CHR(60)||'/Table'||CHR(62) ||
CHR(60)||'/Worksheet'||CHR(62)||
CHR(60)||'/Workbook'||CHR(62);
dbms_output.put_line(l_xls_code);
end;
the above code displays the output. that will be the xml coding that can be stored in the file with '.xls' format
this will be opened via excel sheet only
this file will be having the data from the table.
in the above mentioned example, the data is fetched by cursor and is used to generate the code dynamically.
in the similar way, styles like font, cell color, cell width, etc... can be dynamically defined via plsql and can be coded into the file as per required.
usually this variable would be a clob, lob variable (as in real time scenarios this xml coding would be quite large) that can be sent as an attachment, or to create a file in server location.
similar method can be done via unix scripting - to have the xls coding generated by sql session as per required and to spool them in a file

Oracle sql remove specific tag from string

I want a function to pass a text (varchar2) and a tag name
and return the text with the tag and their child tags removed
Keep only
I don't know how levels of childs there are under tag.
Input :
set serverouput on
declare
v_input_str varchar(4000) := ' <parent1>
<Message>12ab</Message>
<CreationDate>02/08/2015</CreationDate>
<Total>500.45</Total>
<Collect>
<Name>Peter</Name>
</Collect>
</parent1>';
begin
dbms_output.put_line(v_input_str);
end;
/
output :
' <parent1>
<Message>12ab</Message>
<CreationDate>02/08/2015</CreationDate>
<Total>500.45</Total>
<Collect/>
</parent1>'
Thanks in advance
You can use deleteXML for this.
Assuming your parameter tag is stored in tag variable, do:
declare
v_input_str clob := ' <parent1>
<Message>12ab</Message>
<CreationDate>02/08/2015</CreationDate>
<Total>500.45</Total>
<Collect>
<Name>Peter</Name>
</Collect>
</parent1>';
tag varchar2(20) := 'Collect';
begin
select deleteXML(xmltype(v_input_str), '//'||tag||'/*').getClobVal() into v_input_str from dual;
dbms_output.put_line(v_input_str);
end;
Output:
<parent1><Message>12ab</Message><CreationDate>02/08/2015</CreationDate><Total>500.45</Total><Collect/></parent1>

pdf to text conversion using oracle package

i m seeing some strange behavior for my pdf to text conversion using oracle
bellow is the code of a sql file.
create or replace directory pdf_dir as '&1';
create or replace directory l_curr_dir as '&3';
declare
ll_clob CLOB;
l_bfile BFILE;
l_filename VARCHAR2(100) := '&2';
begin
begin
ctx_ddl.drop_policy('test_policy');
exception
when others then
null;
end;
ctx_ddl.create_policy('test_policy','ctxsys.auto_filter');
l_bfile := bfilename('PDF_DIR',l_filename);
dbms_lob.createtemporary(ll_clob, true);
ctx_doc.policy_filter(
policy_name => 'test_policy'
, document => l_bfile
, restab => ll_clob
, plaintext => true
);
ll_clob := REPLACE(TRIM(ll_clob), chr(13), chr(10));
ll_clob := REPLACE(ll_clob, chr(10), chr(32) || '<<EOL>>' || chr(10)||'<<BOL>>');
INSERT into tempclob_op(filename, data) VALUES(l_filename, ll_clob);
DBMS_XSLPROCESSOR.clob2file (ll_clob,'L_CURR_DIR' , 'plaintext.text');
dbms_lob.freeTemporary( ll_clob );
end;
/
problem is i have run this code for 10000 files and it gives correct results for almost all but for almost 10 files it corrupts the output in plaintext.text file. And i dont know why is it happening? Also when i run this sql code for individual files it gives me correct results.
I have added some delay of 2 seconds in every execution while in loop for each file. and seems it resolved the problem strangely ..no concrete answers though.