Excel file generation using SQL query, SPOOL command in Shell script - excel

I have to generate excel file from tables from Oracle Database. The code is working fine but however the column names are not coming completely, there are just coming as the length of there data length.
I want complete header/column names
The column names are coming like this
ST STAT_TYPE_DESC ST S NXT_STATME DELAY_DAYS ANN_PREM_LIM_LOW ANN_PREM_LIM_HI CONTRIB_HIST_LEN EVENT_DO C P
But I want is complete names of the columns, for example ST is STATEMENT_TYPE_ID
#!/bin/ksh
FILE="A.csv"
sqlplus -s lifelite/lifelite#dv10 <<EOF
SPOOL $FILE
SET HEADING ON
SET HEADSEP OFF
SET FEEDBACK OFF
SET LINESIZE 250
SET PAGESIZE 5000 embedded ON
SET COLSEP ","
SELECT * FROM TLLI_01150STATTYPE;
EOF
SPOOL OFF
EXIT 0

Before your select add a new one with the column names:
SELECT 'STATEMENT_TYPE_ID' || ',' || 'STAT_TYPE_DESC' || ',' || ... FROM dual;
And set heading off

Related

BCP QUERYOUT how to change length to all decimal fields

I export SQL tables to txt files (by the code below in ssms)
all the columns are exported well except decimal columns,
which export 41 chars (I want 19 chars),
even the size column is 14(4)
how can I change the settings in order the column will export in the size I want?
notes:
bcp export 0.0 decimal value as .0000 as I need
my tables is very big can't use substring- a lot of columns and a lot of rows
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
-------------
DECLARE #stmtQuery VARCHAR(8000),#stmt VARCHAR(8000);
----שליפת הנתונים מהטבלה
set #stmtQuery ='SELECT * FROM myDB.dbo.HugeTable' --a lot of decimal columns, a lot of rows
--copy data to txt file
SET #stmt = 'BCP "' + #stmtQuery +
'" QUERYOUT "path\to\file\TableData.txt" -t -C RAW -S ' + ##SERVERNAME + ' -d ' + DB_NAME()+' -e path\to\file\log.txt -c -r"0x0A" -T';
EXEC master.sys.xp_cmdshell #stmt;

Unable to append the output of for loop

I am trying to get tablespace total space for those tablespaces where given threshold is breached.
As I am getting more than one tablespaces in output , I am splitting those and after that running a for loop on array. Now I need to get bytes for each i but its only printing value of first occurrence. How should I append all the values?
Please check below code:
output1=`sqlplus -s username/password as sysbackup <<END1
set linesize 200
set head off
select tablespace_name||',' from dba_tablespace_usage_metrics where used_percent > 50;
exit;
END1`
IFS=', ' read -r -a array <<< $output1
for val in "${array[#]}"
do
output2=`sqlplus -s username/password as sysbackup <<END2
set serveroutput on;
set linesize 200
set head off
spool test.txt
SELECT TABLESPACE_NAME, ROUND (SUM (BYTES) / 1048576) FROM DBA_DATA_FILES WHERE TABLESPACE_NAME = '${array[val]}' GROUP BY TABLESPACE_NAME;
spool off;
#test.txt
exit;
END2`
done
#test.sql should print :
SYSAUX 2048
SYSTEM 4027
but its only printing:
SYSAUX 2048
Your code isn't printing anything from the loop at the moment; if you print $output2 after the loop then you'd see that value once; if you did it inside the loop then you'd see it multiple times, with the same value. Each output would also plus an SP-0734 error, which you may be supressing.
When you write to test.txt you're putting the result of the query against dba_data_files into that file; and $val has the value form the array not an index, so ${array[val]} doesn't mean what you probably think, and always gives you the first element in the array; so each time around the loop you've got the same result from the same query in test.txt.
Then you execute that, which gets an error. But both the initial query and that error is all being captured into output2 - just as you'd see it all if you ran test.txt manually. And that is overwritten each time. So if you process/display it inside the loop you'd see the same result repeated; if you ran it after the loop (which is what you seem to be doing, from your description) then you'd see it once.
If you really wanted to append the output each time around the loop you could do:
output2=${output2}`sqlplus -s username/password as sysbackup <<END2
...
END2`
or:
output2+=`sqlplus -s username/password as sysbackup <<END2
...
END2`
but you would need to clean up the output that both queries are producing, and then might need to include a newline in that concatenation.
This would be much simpler as a single query, which just outputs directly instead of to a variable:
sqlplus -s username/password as sysbackup <<END1
set pagesize 0
set linesize 200
set feedback off
SELECT TABLESPACE_NAME, ROUND (SUM (BYTES) / 1048576)
FROM DBA_DATA_FILES
WHERE TABLESPACE_NAME IN (
select tablespace_name
from dba_tablespace_usage_metrics
where used_percent > 50
)
GROUP BY TABLESPACE_NAME
ORDER BY TABLESPACE_NAME;
END1
If you don't want the column alignment then concatenate the name and size values:
SELECT TABLESPACE_NAME || ' ' || ROUND (SUM (BYTES) / 1048576)

Shell script to fetch sql query data in csv file

Need to extract the below query data along with header in csv file using shell script.
Below is the query.
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode,NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UT)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj=0
UNION
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode, NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UTG)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj<>0
Could please let me know if below approach to fetch data using shell script is correct and script is correct.
#!/bin/bash
file="output.csv"
sqlplus -s username/password#Oracle_SID << EOF
SPOOL $file
select 'SourceIdentifier','SourceFileName','ProfitCentre2','PlantCode',
'tax_retur ReturnPeriod','document_number DocumentNumber','TO_CHAR(invoice_generation_date,'YYYY-MM-DD') Docume','Original','customer_name CustomerName','NVL(sns_pos,new_state_code)POS','PortCode','NEW_HSN_CODE HSNorSAC','(SGSATE+UTGSATE) Stat','(SGS+UT)StateUT','Userde' from dual
Union all
select 'TO_CHAR(SourceIdentifier)','TO_CHAR(SourceFileName)','TO_CHAR(ProfitCentre2)','TO_CHAR(PlantCode)',
'TO_CHAR(tax_retur ReturnPeriod)','TO_CHAR(document_number DocumentNumber)','TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume','TO_CHAR(Original)','TO_CHAR(customer_name CustomerName)','TO_CHAR(NVL(sns_pos,new_state_code)POS)','TO_CHAR(PortCode)','TO_CHAR(NEW_HSN_CODE HSNorSAC)','TO_CHAR((SGSATE+UTGSATE) Stat)','TO_CHAR((SGS+UT)StateUT)','TO_CHAR(Userde)' from
(SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode,NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UT)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj=0
UNION
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode, NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UTG)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj<>0)
SPOOL OFF
EXIT
EOF
In short: the ; is missing from the end of the select statement.
Some unrequested advice:
I think spool will put extra stuff into your file (at least some new lines), a redirect is better, further the first line is not db-related:
echo "SourceIdentifier;SourceFileName;ProfitCentre2..." > $file
I recommend to generate the csv format right in the select query, later it will be more headache (you can escape there what you want):
$query = "select SourceIdentifier || ';' || SourceFileName || ';' || ProfitCentre2 ... ;"
So querying the DB (I think capital -S is the right one) plus for the formatting of the records (and maybe you want to format your columns too):
sqlplus -S username/password#Oracle_SID >> $file << EOF
set linesize 32767 pagesize 0 heading off
$query
EOF
For me this one is working but one empty line before first query and second query is coming. Empty line remove using awk command
#!/bin/bash
FILE="A.csv"
$ORACLE_HOME/bin/sqlplus -s username/password#Oracle_SID<<EOF
SET PAGESIZE 50000 COLSEP "," LINESIZE 20000 FEEDBACK OFF HEADING off
SPOOL $FILE
select 'TYPE_OF_CALL_V','SWITCH_CALL_TYPE_V','RECORD_TYPE_V','TARF_TYPE_V' from dual;
SELECT TYPE_OF_CALL_V,SWITCH_CALL_TYPE_V,RECORD_TYPE_V,TARF_TYPE_V FROM TABLE;
SPOOL OFF
EXIT
EOF
awk 'NF > 0' $FILE > out.txt
mv out.txt $FILE

SQLPLUS formatting output in excel

Below is the code to retrieve data from DB and output it in excel
sqlplus -s ${uidpwd} <<EOF
SET PAGESIZE 50000
SET FEEDBACK OFF
SET MARKUP HTML ON
SET NUM 24
SPOOL Extract.xls
whenever oserror exit 9
whenever sqlerror exit sql.sqlcode
#${SQL_SCRIPT}
SET SERVEROUTPUT ON
SET ECHO OFF
SET VERIFY OFF
SPOOL OFF
SET MARKUP HTML OFF
quit;
EOF
But what i see in excel report is all numbers in excel are with exponential like "5.30056E+15"
i tried below options, but none of them worked
SET NUMBERFORMAT '9999999999999999999999'
SET NUMWIDTH 20
in SQL i tried below
to_char(conf_num, '999999999999999999999999')
SELECT ' '||conf_num "Confirmation Number"
Also i have exec > ${LOGPATH}/log.``date +"%y%m%d"``.log 2>&1 in my script, Query out put is getting written in to this log file, how to avoid that? It should have only error logs.

sqlplus Input redirection on bash

New to sqlplus/bash scripting. I currently have a simple script that fetches some value in a table based on some ID values.
#do things. get login info. etc....
(cat<<HERE
set heading off;
select data_value from metadata where name='JOHN' and uniqueid in (1, 2, 3);
EOD
) | sqlplus -S $login
#do things.
What if instead of having to manually type of the ids (1, 2, 3, etc...), I do this:
#calls a script that gets the IDs from somewhere and outputs it in the correct format
./getIDscript > IDs
#do things. get login info. etc....
(cat<<HERE
set heading off;
select data_value from metadata where name='JOHN' and uniqueid in ($IDs);
EOD
) | sqlplus -S $login
#do things.
Would this work? I currently won't have access to the school lab for a few days so I can't test this out right now.
Is there a better and more efficient way of doing this?
Try this :
sqlplus -S /nolog <<_EOD1
WHENEVER SQLERROR EXIT SQL.SQLCODE
connect usr/xxx#db1
select 1 from dual
/
exit
_EOD1

Resources