Oracle Spool Function: Heading Won't Show - sql

I am trying to export an Oracle SQL+ query as a txt file. So far everything works, BUT I need to get the heading to show in my query. For whatever reason, even with Set Heading On checked, it still doesnt work. Where am I going wrong?
column Fruit Format a15;
column Quantity Format a15;
SET LINES 32000
SET TERMOUT OFF ECHO OFF NEWP 0 SPA 0 PAGES 0 FEED OFF TRIMS ON TAB OFF ECHO OFF PAGESIZE 0
SET HEADING ON
select
fruit as Fruit,
number as Quantity
from fruit_table;
spool test.txt
spool off

The problem is this part of your SET statement:
PAGES 0 ... PAGESIZE 0
In SQL*Plus, pagesize (or pages, the one is short for the other) means "after how many lines do you want the heading to repeat?" The default is 20, so we get the heading repeated every twenty rows.
It's counter-intuitive, but setting pagesize to 0 has the effect of suppressing the headings, regardless of the value of heading.
Incidentally, you need to put the SELECT command between the spool ... and spool off. Otherwise you'll end up with an empty file.

Related

Add System Date to file name during Oracle SQL Run

I am running the following code in SQL developer (oracle) to run the query and export a csv file into a folder. I would like to add the system date to the filename as well. I am using the following code. Although it does the job, it asks the user to input the date in the pop up window. I am looking to get rid of the pop up window and rather have the code use the system date instead. Is there any way i can eliminate the user input window?
Second issue is that this also brings in the SQL code to the output file along with the query results, is there any way to avoid bringing in the SQL as well?
set VERIFY off
set FEEDBACK off
set echo off
set heading off
col date_stp new_value date_stp
Select to_char(sysdate,'yyyymmdd') date_stp from dual;
Spool 'I:\Folder\ExportData&date_stp..csv';
SET sqlformat csv;
Select Customer, ID, etc -- the content of the query
Spool off;
Here's how: in order to avoid displaying the select statement within the spooled file, you need to
set term off
set feed off
but not directly in SQL*Plus (or SQL Developer); you'll have to save the following contents into a .SQL file and run it using #.
So: p.sql
set term off
set feed off
col sd new_value x
select to_char(sysdate,'YYYYMMDD') sd from dual;
spool dept&x..txt
select * From dept;
spool off
Testing:
SQL> #p --> call the .sql file
SQL> $dir *.txt
Volume in drive C is OSDisk
Volume Serial Number is 7635-F892
Directory of C:\Users\lf
12.06.2020. 21:13 494 dept20200612.txt --> file name is OK
1 File(s) 494 bytes
0 Dir(s) 260.040.732.672 bytes free
SQL> $type dept20200612.txt
--> no SELECT statement here
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
In order to stop SQL*Plus or SQL Developer asking for value of a substitution variable (that's what &something represents), run set define off.

Problems while spooling data from Oracle. It spools elapsed time instead of spooling result of sql query into output file

I am trying to make a cron job that runs once a day. On invoking the shell script, it calls a Sql file. Which in turn Spools data into a file. This file is Picked by Shell Script and then mailed accordingly. Problem is when I try to spool data , it is writing elapsed time instead of writing actual result of query to the output file.
Here is the sql file I am using.
set define off
set numformat 99999999999999999999999999
set markup html on
set serveroutput on
set head on
set pages 3000
set echo off
DECLARE
total integer :=0;
total = select count(*) from t_c_table1 vt, t_c_table2 ti WHERE vt.f_item_id = ti.f_item_id (+) AND (f_update_date < sysdate - 30)order by F_INSERT_DATE desc;
IF total > 0 then
spool /home/output.csv
select f_name, count (*) from t_c_table1 where F_INSERT_DATE < sysdate-100 group by f_item_provider_id;
spool off
END IF
I get output like Elapsed: 00:00:00.506 in the spooled csv file.
Where am i going wrong?
Please Help.
Thanks in Advance..
Code you posted is wrong, it won't even compile in Oracle so I'm surprised that you got anything at all.
As there's no SET TIMING ON, I'm not sure what produced the elapsed time line in the spooled file. Maybe it is some old, previously created CSV file you're looking at?
Apart from the fact that SPOOL is a SQL*Plus command (so you can't invoke it in a PL/SQL procedure), the way you calculated the TOTAL variable's value is wrong - it should be part of the SELECT ... INTO statement.
SQL> declare
2 total integer := 0;
3 begin
4 select count(*)
5 into total
6 from dept;
7
8 if total > 0 then
9 spool test.csv
10 select * from dept;
11 spool off;
12 end if;
13 end;
14 /
spool test.csv
*
ERROR at line 9:
ORA-06550: line 9, column 12:
PLS-00103: Encountered the symbol "TEST" when expecting one of the following:
:= . ( # % ;
SQL>
If you want to spool data conditionally, you'll have to use the UTL_FILE package.
Or, you could do it "interactively" so that SQL*Plus asks you whether you want to spool data or not, as Alex Poole described in his answer here.

Export from sql to excel

I run a query using sqlplus command line interface. The query will fetch some 30 million records. I need to export the result to either csv or xls format. Can anyone let me know if this is possible?
Any help is much appreciated.
Thanks in advance.
Try spool myresults.csv before your select statement, which Excel can easily open.
EDIT
Like this:
SET UNDERLINE OFF
SET COLSEP ','
--That's the separator used by excel later to parse the data to columns
SET LINES 100 PAGES 100
SET FEEDBACK off
--If you don't want column headings in CSV file
SET HEADING off
Spool ~\myresults.csv
--Now the actual query
SELECT * FROM YOUR_TABLE;
Spool OFF
EDIT 2
You might want to batch your results if you're going to query 30M records. I've never gone that far in an excel file but the limit is 65535 rows (that would be 458 files for 30M records).
I'd go with cutting up your query into block of 60K blocks and spooling each select to a different excel file, maybe by looping on an integer and concatenating it to the end of each filename.
SET PAGESIZE 50000
SET FEEDBACK OFF
SET MARKUP HTML ON SPOOL ON
SET NUM 24
SPOOL sample.xls
SELECT * from users;
SPOOL OFF
SET MARKUP HTML OFF SPOOL OFF
This option will help you to export directly to a excel file
SET PAGESIZE 40000
SET FEEDBACK OFF
SET MARKUP HTML ON
SET NUM 24
SPOOL file_name.xls
---- Execute your query
SPOOL OFF
SET MARKUP HTML OFF
SPOOL OFF
Spool sqlplus to xls format

Column title SQL Script

How can i add column name on top of the column in sql generated xls ouput file.. I am getting all the data but without column heading .. I am doing this in c shell sql script.. I have my SET HEADINGS ON but still i am not getting my heading.. do i have to do anything else in the sql script to populate the heading...plz help
`SET PAGESIZE 0
SET LINESIZE 1000
SET LONG 100000
SET FEEDBACK OFF
SET ECHO OFF
SET HEADING ON
SET SPACE 1
SET FLUSH OFF
SET TRIMSPOOL ON
SET NUMFORMAT 9999999999.90
SELECT USER_ID
From ...
Where...;`
please share us your query. What client tool do you use?
Asuming you use sql*plus
set heading on
set pages 10000
select dummy user_id
from dual;
It's the SET PAGESIZE 0 that is causing the normal heading to be suppressed.
SET PAGESIZE
Sets the number of rows on each page
of output in iSQL*Plus, and the number
of lines on each page of output in
command-line and Windows GUI.
Increase PAGESIZE to avoid printing
headings frequently, or set it to 0 to
prevent headings being displayed.
So one option is to set pagesize to a very large value (50,000 is the largest allowable value in my version of SQLPlus).
If your query is going to produce more rows than that, you will have heading appearing in the middle of the data. So another option is to keep headings off and add a separate statement to your script to output a header row. You could use SELECT 'USER_ID FROM DUALorPROMPT USER_ID` to output the text "USER_ID".
SELECT COLUMN_NAME might be what you're looking for...

SQL debug print

If you have 100 occurrences of "PRINT" in your stored procedure, is there a nice way to turn them all on/off when debugging an non-debugging?
I could add a variable #isdebug = 1
and later on, do something like
IF #isdebug = 1 PRINT #yourvar
and then just set the #isdebug to 0 or 1 depending on what you need.
Is there a nicer way to do this?
Nope, that is also what I have in procs
IF #debug = 1
BEGIN
print 'Something'
--or insert into a log table if you need the rows of a temp table
--or the results of a calculation
END
An expansion of this idea is to setup up a controlling string. This giving us more options rather than either on or off.
For example:
Stored procedure parameter declaration
(#Debug varchar(5), -- use bit wise control for debugging, currently 5 levels.
Simple substring to drive a testing/debug block.
if substring(#Debug, 1, 1) = '1'
For a test run you could enter '10001' for #Debug so that "level" 1 debugs show (ie initialisations) and only "level" 5 debugs show for the sub-section of code you are testing/debugging.
You could expand on this idea by using number values (ie 2-9) too. But that might be too over the top.