I want to use spool functionality in Oracle 11g.
I want the entire output to be spooled into a file and a subset of the output to be spooled into a separate file.
In the below example I want temp_1.txt to contain data from A,B,C,D and E
In temp_2.txt I want data only for D.
sqlplus user/pass#inst
spool on temp_1.txt
select * from A;
select * from B;
select * from C;
spool on temp_2.txt
select * from D;
spool off temp_2.txt
select * from E;
exit;
Note:- Since this is very old legacy code I can't write a separate sqlplus session for D or re order the selects.
How about doing it all in the sqlplus script. The host commands will need to change if you ever run on a different system (ie. Microsoft Windows). But, they would be required to change in a shell script as well.
spool all_queries.txt
select * from A;
select * from B;
select * from C;
spool off
spool only_d_query.txt
select * from D;
spool off
host cat only_d_query.txt >>all_queries.txt
spool all_queries.txt append
select * from E;
spool off
You can't do that. The SPOOL command only allows one open file at a time; your second command, which would be spool temp_2.txt (without the on) would close the first file before opening and starting to write to the second one. And off doesn't take any further parameters.
Usage: SPOOL { <file> | OFF | OUT }
where <file> is file_name[.ext] [CRE[ATE]|REP[LACE]|APP[END]]
One solution would be to spool the output of the statements to different files:
spool temp_1.txt
select * from A;
select * from B;
select * from C;
spool temp_2.txt
select * from D;
spool temp_3.txt
select * from E;
spool off
... and then combine all three files into one from the operating system to get your 'master' output file, while still retaining the D-only file separately. e.g.:
cat temp_2.txt >> temp_1.txt
cat temp_3.txt >> temp_1.txt
rm temp_3.txt`
Which leaves temp_1.txt and temp_2.txt with the content you wanted, if I've understood you correctly. Different method if you're on Windows, of course.
Alternatively you could run the queries in a PL/SQL block and use UTL_FILE to write the results to one or both of two open files. But that's a bit more work, and would write the files on the server - so you'd need permissions on a DIRECTORY object to write to, and access to the underlying filesystem directory that points to in order to retrieve the files.
Related
I am having trouble creating a .sql batch file that can execute a select statement on SQL Developer.
This is my code:
set pagesize 500
spool #c:\temp\output.log
set echo on
SELECT OBJECT_NAME
FROM DBA_OBJECTS
WHERE OBJECT_TYPE = 'TABLE'
AND OWNER = 'DWBATCH'
GROUP BY = 'OBJECT_NAME'
spool off
The script will display the original output, and the select statement is not being executed. I will appreciate any input to what is wrong with this script, since it should work according to my knowledge.
Can someone explain how to create a text file and save to my C drive from a select query? Anytime I run the query I would like the query to replace the old text file with the new query data.
You will need to follow the steps :
save this in file named get_data.sql
SET HEADING OFF
SET FEEDBACK OFF
SET TERM OFF
SET LONG 100000
SPOOL Dept_100.txt
select 'EmployeeName : '||Emp_id from Employee where Deptno = 100;
SPOOL OFF
on CMD, Go to the folder where the script is.
connect using sqlplus through command prompt.
Run the script
SQL>#spool.sql
spool.sql contains select statement which will select employeename of all employees who work for Dept :100(Just for example).
running spool.sql will create a file "Dept_100.txt" containing employeenames.
I have a file called table.txt which stores the table names. I want the sql update query to take the table name one by one from my table.txt file. My code is as follows:
while read LINE1; do
`sqlplus username/pwd#tname <<END |sed '/^$/d'
set head off;
set feedback off;
update &LINE1 set enterprise_id = '1234567890' where enterprise_id is NULL;
update &LINE1 set sim_inventory_id ='1234567890';
COMMIT;
exit;
END`
done < table.txt
it gives an error sqlplus not found. Can you please tell what is wrong?
This is nothing to do with passing the table names. The "sqlplus not found" error means it cannot find that binary executable, so it isn't getting as far as trying to connect or run the SQL commands.
Your shell script can only see environment variables from the calling shell if they were exported. If you've modified your PATH to include the location of the sqlplus binary then you may not have exported it; add export PATH after you set it.
Or you can set the script up to not rely on the shell environment.
export ORACLE_HOME=/path/to/oracle/installation
export PATH=${ORACLE_HOME}/bin:$PATH
export LD_LIBRARY_PATH=${ORACLE}/lib:${LD_LIBRARY_PATH}
while read LINE1; do
sqlplus username/pwd#tname <<END |sed '/^$/d'
set head off;
set feedback off;
update &LINE1 set enterprise_id = '1234567890' where enterprise_id is NULL;
update &LINE1 set sim_inventory_id ='1234567890';
COMMIT;
exit;
END
done < table.txt
Incidentally, updating the same table twice isn't necessary; you could do:
update &LINE1 set enterprise_id = nvl(enterprise_id, '1234567890'),
sim_inventory_id ='1234567890';
It would also be quicker to create a list of all the update statements from your file contents and run them all in a single SQL*Plus session, so you aren't repeatedly creating and tearing down connections. But that's outside the scope of what you asked.
Figuring out how to spool to a file has been easy enough. I am hoping there is an option to write to the text file after each command is written. I am not sure how to communicate the status of a long script to other people on my team. The solution we were going for was to write a log file to a network drive, as the script executes they would be able to follow along.
However, this seems to only write output to the file after the spool off; command at the end of the file.
Is there any way to achieve what we're trying to do, either with spooling a log file or another method?
Here is the code I have so far.
set timing on;
set echo on;
column date_column new_value today_var
select to_char(current_timestamp, 'yyyymmdd_HH24_MI') as date_column
from dual
/
select current_timestamp from dual;
SPOOL 'Z:\log\KPI\secondary_reporting_&today_var..log'
... lots of stuff...
spool off;
As far as I know there's no way to control when spooled output is written to a file. One way around this, though, could be to abandon spooling altogether and just redirect the output:
$ sqlplus #/path/to/script.sql >& /path/to/script.log
Two methods come to mind, depending on what your 'stuff' is.
1) If your code has lots of SQL statements and PL/SQL blocks then you can repeatedly spool for a little while. Use the spool <filename> append statement for this.
SQL> help spool
SPOOL
-----
Stores query results in a file, or optionally sends the file to a printer.
In iSQL*Plus, use the Preferences screen to direct output to a file.
SPO[OL] [file_name[.ext] [CRE[ATE] | REP[LACE] | APP[END]] | OFF | OUT]
Not available in iSQL*Plus
2) If you have long running PL/SQL procedures use the UTL_FILE package. See https://docs.oracle.com/html/B14258_02/u_file.htm for more information. This does require some setup and administrative privileges in the database to set up a directory where writing is allowed.
I am very new to oracle.I need to create a file with the system timestamp from oracle. Please let me know how do i do that.
More over I need to write any exceptions or errors thrown by my pl/sql code to a file and exit after an error. How do i do this?
Thanks,
Priya.R
It seems you want to look into the UTL_FILE Oracle supplied package, as you're trying to use PL/SQL to create the file.
You can generate the file this way:
(You'll need to create an Oracle DIRECTORY first, pointing to the OS location of the file:
CREATE OR REPLACE DIRECTORY DIR AS 'your OS directory';
Note that the name 'DIR' is used in the sample code that follows. You will also require the CREATE DIRECTORY privilege, and then grant read and write permissions on the directory to the user who will use it:
GRANT READ,WRITE ON DIR TO user1;
)
DECLARE
v_logfile VARCHAR2(100);
v_FH UTL_FILE.FILE_TYPE;
BEGIN
v_logfile := TO_CHAR(SYSDATE,'YYYYMMDD HH24MISS')||'_process.log';
v_FH := UTL_FILE.FOPEN(DIR, v_logfile, 'w');
UTL_FILE.PUTLINE(v_FH, 'Some text on a new line');
UTL_FILE.FCLOSE(v_FH);
END;
This is how you can get a dynamic filename in SQL Plus
SET TERMOUT OFF
DEFINE dynamic_filename = idle
COLUMN which_dynamic NEW_VALUE dynamic_filename
SELECT 'prefix_'
||TO_CHAR( SYSDATE, 'YYYYMMDD' )
||'_'
||TO_CHAR( SYSDATE, 'HH24MISS' )
||'.log' which_dynamic
FROM dual;
SET TERMOUT ON
SPOOL &dynamic_filename
SELECT * FROM dual;
SPOOL OFF
The file gets created in the default directory for SQL Plus (on windows this is the "Start In:" property of the shortcut)
To place the output in a known directory amend the SPOOL command to something like...
SPOOL c:\output_dir\&dynamic_filename
To get an SQL Plus script to exit after an error then include this command...
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK