i'm trying to make a log file with sql, that contains a header, but i am getting this error : ORA-01756: quoted string not properly terminated , because of the semicolon, that my header should contains.
select 'User. Name;
User. Number;
User. Data;' from dual;
Kind regards,
run them in one line like this. If you want them in new line add chr(10) :
select 'User.Name;'||chr(10)||'user.Number;'||chr(10)||'User.Data;' from dual;
because oracle consider ; as to execute the command
If you need to write something in a spool file by SQLPlus, you can simply use PROMPT:
PROMPT User. Name; User. Number; User. Data;
or, if you need to print 3 rows:
PROMPT User. Name;
PROMPT User. Number;
PROMPT User. Data;
If you're using spool and want header to your query please execute before query:
SET HEADING ON
SET PAGESIZE 50000
PAGESIZE should be something big as this means after how many line header will be repeated.
Related
I'm working on a solution where several SQL and PL/SQL scripts are being run together, in a batch of sorts, via SQL*Plus.
I'm declaring SET ECHO OFF; and SET ECHO ON; at relevant points in the scripts so as to output relevant code.
Currently the output looks something like this:
SQL> DECLARE
2 ct number := 0;
3 ctChanges number := 0;
4
5 BEGIN
6 select count(*) into ct from ...
7 (...rest of code block...)
"some specific status message"
Commit executed.
We keep this output as a run-log in our build-environment, but can also access it as a plain text file.
One downside of this format however, is that if I'd like to copy a certain section of the code and run it again in an IDE (like Toad or SQL Developer), it's hard to exclude the line numbers.
Is it possible to tell SQL*Plus to output the code as above, but without including the line numbers?
You can use options sqlnumber and sqlprompt:
set sqlprompt ''
set sqlnumber off
SET SQLN[UMBER] {ON|OFF}
SET SQLNUMBER is not supported in iSQL*Plus
Sets the prompt for the second and subsequent lines of a SQL command or PL/SQL block. ON sets the prompt to be the line number. OFF sets the prompt to the value of SQLPROMPT.
I want to export one table to each csv file and name the csv file with timestamp. For example, if I have a table t1, after export, a csv file name t1.YYYYMMDDHHMISS.csv is generated. Here is my code:
create or replace procedure
T_to_CSV(Tname varchar2,Directory varchar2)
BEGIN
set colsep , -- separate columns with a comma
set pagesize 0 -- No header rows
set trimspool on -- remove trailing blanks
set headsep off -- this may or may not be useful...depends on your
spool timestamp.csv --don't know how to write in directory
select *
from Tname
end
Here are my questions:
(1) I don't know how to output the csv file into the requried directory, how to fix the spool code please?
Should I use spool D:\path\filename.csv please?
(2) In the spool line, how to change the name of the csv file using the timestamp now() please?
There are a few steps:
create a directory using `CREATE DIRECTORY my_dir as 'C:\dir';
make sure that Oracle has read,write on the folder on the computer (best accomplished by creating it in the Oracle install folder)
grant the user executing the procedure GRANT read,write on DIRECTORY my_dir to the_user;
download and compile the handy procedure here
I have used this and it works really nicely.
Usage
data_dump ( 'Select emp_name from emp',
CURRENT_TIMESTAMP||'filename.csv',
my_dir);
(vastly simplified sample!)
After creating the directory verify your work by running this:
Select * from ALL_DIRECTORIES;
you should see your directory
logon to the machine where the database is located and verify the folder path exists and the oracle user has permissions on it. Networked drives are only possible if the user running the oracle service has permissions on that folder
Thanks kevin for sharing the procedure and it was very useful for me. I have customized the code:
To Add the column names in the output csv file which was not working earlier.
When i was passing the delimiter as parameter then it was adding the comma in the starting of every row(,1,2,3) which has been corrected.
I am also sharing the customized code which might help others. Customized code can be downloaded here.
Customized Code to add column names
FOR i IN t_describe.FIRST .. t_describe.LAST LOOP
IF i <> t_describe.LAST THEN put('UTL_FILE.PUT(v_fh,'''||t_describe(i).col_name||'''||'''||v_delimiter||''');');
ELSE
put(' UTL_FILE.PUT(v_fh,'''||t_describe(i).col_name||''');');
END IF;
END LOOP;
put(' UTL_FILE.NEW_LINE(v_fh);');
Customized Code for delimiter
IF i <> t_describe.LAST THEN
put(' UTL_FILE.PUT(v_fh,"'||t_describe(i).col_name||'"(i) ||'''||v_delimiter||''');');
ELSE
put(' UTL_FILE.PUT(v_fh,"'||t_describe(i).col_name||'"(i));');
END IF;
And the correct way to call the procedure is to bind the variable with values
data_dump(query_in => 'Select 1 from dual',file_in => 'file.csv',directory_in => 'MY_DIR', delimiter_in => '|' );
Thanks
Naveen
Save and copy file in a directory {file need not be executable}
Export ORACLE_HOME, PATH and SID of database instance
Navigate to that directory and execute sqlplus
Spool file will be created in the same directory as the .sql file
SET COLSEP ,
SET HEADSEP OFF -- character used when defining a two-line column heading
SET TRIMSPOOL ON -- trim trailing spaces from each line
SET LINESIZE 32000 -- number of characters to be printed on one line
SET WRAP OFF -- truncates lines longer than LINESIZE
SET NUMWIDTH 5 -- default width while displaying numbers
COLUMN tm new_value iso8601 noprint
SELECT to_char(sysdate, 'YYYY-MM-DD') tm FROM dual;
spool output_file_&iso8601..csv
-- Append new data to spool file: "spool output_file_&iso8601..csv append"
SELECT
*
FROM
table_name
spool OFF
DECLARE
V_NUMBER NUMBER :=23;
BEGIN
LOOP
V_NUMBER:=V_NUMBER+1;
EXIT WHEN V_NUMBER:=25;
--Some kind of function to be applied for printing and nesting lines into CSV or TEXT file.
END LOOP;
COMMIT;
END;
Scripting an Oracle SQL Query for Creating a CSV or Text Typed File Output
Consider running this from a SQL Plus session and use the SPOOL command. All output of the SQL command that follows will be written to the file name you specify.
If you need to append your results each successive time the SQL commands are run, then an OS level command would work appropriately when invoking this sqlplus executable block of PL/SQL:
Where the file name of this script is: "sample_csv_out.sql"
DECLARE
v_total_columns constant number:= 3; -- Number of columns queried
v_column_counter number;
v_csv_record varchar2(1000);
c_csv_column_format constant varchar2(15):=
'<<COLUMN1_VAL>>,<<COLUMN2_VAL>>,<<COLUMN3_VAL>>';
cursor result_cur is
SELECT column1, column2, column3
FROM tablea
WHERE column1 = ... ;
BEGIN
v_csv_record:= 'COLUMN1,COLUMN2,COLUMN3';
dbms_output.put_line (v_csv_record);
FOR i in result_cur LOOP
v_csv_record:= replace(c_csv_column_format, '<<COLUMN1_VAL>>', i.column1);
v_csv_record:= replace(v_csv_record, '<<COLUMN2_VAL>>', i.column2);
v_csv_record:= replace(c_csv_record, '<<COLUMN3_VAL>>', i.column3);
dbms_output.put_line(v_csv_record);
END LOOP;
END;
So, for example in a WINDOWS O/S environment, the call to append the output to a specific file name would be:
C:\> sqlplus sample_csv_out.sql >> mycsv_out.csv
The >> notation instructs the operating system to pipe the output of running sample_csv_out.sql via a sqlplus session.
The command DBMS_OUTPUT does the rest. If you need more details, see more Oracle documentation on DBMS_OUTPUT.
COMMENTS: I chose the RECORD STRING TEMPLATE approach to make this script a little more flexible and reusable. I recommend to keep any data manipulation logic within the CURSOR statement. Often when the two are mixed, it gets harder to debug any typos in syntax within a long string of values.
The construction of an output record was also designed to reduce typos, mistakes and frustration... if there are more than 3 columns in your own scripts, adding another element to the output string is mostly a cut-and-paste operation. Likewise with the "header" row (column titles).
You can read and write files in PL/SQL using the UTIL_FILE package
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_file.htm
I have a batch files which when i run calls a SQL file. This SQL file prompts user to input data which I store in MYPeriod( this accepts date as input ).the output of SQL file is a CSV file.
Here is my code for SQL file:
PROMPT Enter a period
ACCEPT MYPeriod PROMPT 'Period: '
SET LINESIZE 500 FEEDBACK OFF TRIMSPOOL ON TERMOUT OFF HEAD OFF PAGESIZE 0 TERM OFF
spool E:\abc\Test\File1_&MYPeriod.csv
select Account || ',' || Membername || ',' || GROUP || ',' || FUTURE1 from ACTUAL_V#UAT1_Test where Key=21 and period_name= '&MYPeriod' ;
spool off
exit
My queries :
When I run this , a file gets generated in location E:\abc\Test with a name File1_12-2012csv.Lst. I want a csv file .
If i hard code the file name(replace &MYPeriod by test) File1_Test.csv gets generated perfectly.Why the code is not able to create file with the name user has input..?
The output of this creates a csv file and retrieves the accounts from db but it prints two extra line at top. The new query and old query. How do I redefine my code, so that it gets remove automatically.
Appreciate your help guys.
Substitution variables are optionally terminated by a period to separate them from any characters that follow. If you want to use one in the string as well, you have to add that termination explicitly:
spool E:\abc\Test\File1_&MYPeriod..csv
For the two extra lines issue, add set verify off; at the moment it is set to on (by default) so it shows you the old and new value of any substitution variables you use.
The only way I know to get the date into the file name is to put it into a substitution variable first:
set termout off
column x_run_dt new_value y_run_dt
select to_char(sysdate, 'YYYYMMDDHH24MISS') as x_run_dt from dual;
set termout on
spool E:\abc\Test\File1_&MYPeriod._&y_run_dt..csv
The new_value clause lets you create a substitution variable, &y_run_dt in this case, with a value from a queried column, x_run_dt. Wrapping the select that generates that value between set termout clauses hides it from the normal output, when run as a script.
Code:
set heading off
set arraysize 1
set newpage 0
set pages 0
set feedback off
set echo off
set verify off
spool 'c:\farmerList.csv'
/
select FIRSTNAME','LASTNAME','TRN','CELL','PARISH
spool off
The file is being saved to the directory, however it is saving the "select FIRSTNAME','LASTNAME','TRN','CELL','PARISH" and not the results of the query in csv format. What am i doing wrong?
Your select is incomplete as you don't have a from clause, but not sure if you've lost that in the copy-and-paste. As it is there is nothing to run, since the partial statement is never executed (no terminating ; or / on the next line). If you did have a from farmers; clause then it would show the command plus an ORA-00923 error, probably.
You can't just put a quoted comma between the fields, you need to concatenate the fields with that character using the || concatenation symbol:
spool 'c:\farmerList.csv'
select FIRSTNAME
||','|| LASTNAME
||','|| TRN
||','|| CELL
||','|| PARISH
from farmers;
gives a file containing
Joe,Grundy,X,Y,Ambridge
The fields don't have to be on separate lines, I jut find that easier to read and keep track of the commas.
You don't need the / after the spool command - that will re-excute the last statement before the spool, if there is one - and you don't need the quotes around the spool file name unless it contains spaces, but they don't hurt.
There's also a set colsep command which you can use to make the column separator into a comma, but you have to worry about padding, so I find it easier to concatenate the columns together as you're (almost) doing.
Except that's for SQL*Plus, as I didn't notice the SQL Developer reference in the title. Spool is a bit odd in Developer as it seems to trap and echo things you probably don't want, and not all of the set commands work (which ones depends on the version).
The safer and preferred way, I think, is to run a normal query without concatenated commas:
select FIRSTNAME, LASTNAME, TRN, CELL, PARISH
from farmers;
and with 'run' rather than 'run script', so that the results appear in the grid view in the query result window. Right-click on the grid and choose 'export'. You can then save as a CSV, or even as an XLS, and can choose to not have a header row if you prefer.
this is the correct solution please go through this
import java.sql.*;
import java.io.*;
import au.com.bytecode.opencsv.CSVWriter;
public class TableExport {
public static void main(String[] args) {
try{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE","name","password");
conn.setAutoCommit(false);
Statement statement = conn.createStatement();
ResultSet resultData = statement.executeQuery("select * from your_table");
CSVWriter writer = new CSVWriter(new FileWriter(new File("D:/Uploads/Output5.csv")), '|');
writer.writeAll(resultData, true);
writer.close();
}catch (Exception e){
System.out.println("Error" +e);
}
}
}
if anyone likes this please note you would need oracle-jdbc.jar and opencsv1.7.jar in library folder to properly execute this code.