Issues when user input data in sql command - sql

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.

Related

Oracle SQLPlus: Echo without line numbers?

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.

Need double quotes in each column while spooling data from oracle database to Excel file

I am automating a process wherein I run a SQL query through batch and the output is spooled into a csv file.
Requirement: Each field of csv file should have double quotes.
Ex :
Currently the output is PROJ_SHORT_NAME,WBS_SHORT_NAME
CGL1,CGL1
Required output is "PROJ_SHORT_NAME","WBS_SHORT_NAME"
"CGL1","CGL1"
SQL Query :
set verify off
set trimout off
set trimspool off
set feedback off
set linesize 22000
set pagesize 200
col csv_string FORMAT a1200
set colsep ','
SET UNDERLINE OFF
SET ECHO OFF
SPOOL E:\PDE_GPO\outputfile1.csv
select * from <tablename>;
SPOOL OFF
exit;
The || concatenates items together.
You can do:
SELECT '"'||col1||'","'||col2||'","'||...
FROM table
That would produce something like:
row 1: "col1val","col2val","col3val"...
row 2: ...
The down-side is you have to list/know every column you want to pull, but best coding practices would state you should specify the columns anyways (in case things are added/removed you want to be sure you get what you want).
-Jim
I got the solution for this.
I had to import set markup csv on and the issue got resolved.

Adding a header to an exported file sql

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.

Export table to csv file by using procedure (csv name with timestamp)

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

Favorite SQL*Plus tips and tricks [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
So many times I just need a quick connection to an Oracle DB, where SQLPLUS handles the job.
I imagine when people start using Oracle, the first thing they are told to do is to install Toad or SQLDeveloper. Even so, sometimes you don't want to wait for those tools to load, if you are performing some simple queries.
I have a script that I run when I start my shell so I get a better experience:
SET pagesize 2000
SET LONG 10000
SET linesize 1000
COLUMN last_name format a20
COLUMN total format 999,999,999
SET feedback ON
alter session set nls_date_format = 'yyyy-mm-dd hh:mi:ssPM';
I trimmed my "COLUMN" settings for this example, but basically, that helps the data fit on the screen.
Setting the date format really simplifies dealing with dates.
When the command window opens in Windows, I set the window layout properties so I can scroll, have a wider window, etc. and save the settings for future windows.
Does anybody else use SQL*Plus daily? Any tips?
You can use rlwrap to add readline support to sqlplus. Run sqlplus like this:
$ rlwrap -c sqlplus username#database
Now up/down will scroll through command history. Use ctrl-r to search backwards through history, etc. This makes sqlplus bearable.
Also, add this to your login.sql to set the linesize to whatever the width of your terminal is:
HOST echo "set linesize" $(stty -a|head -n1|cut -f7 -d' '|cut -f1 -d';') > .tmp.sql
#.tmp.sql
HOST rm -f .tmp.sql
Both of these tips only work on unix.
Yes, I use SQL Plus every day in preference to Toad or SQL Developer (though I also use SQL Developer to browse the database).
I have the following in my login.sql script (which SQL Plus runs automatically):
1) Replace default editor (Notepad) with one of my choice:
define _editor = "C:\Program Files\TextPad 5\TextPad.exe"
2) Make SQL prompt show database name so I know where I am (thanks to Tom Kyte for this):
COLUMN global_name new_value gname
SET TERMOUT OFF
SELECT LOWER(USER) || '#' || global_name||CHR(10)||'SQL> ' AS global_name
FROM global_name;
SET SQLPROMPT '&gname'
SET TERMOUT ON
... plus other setting similar to yours.
I also find Tom Kyte's print_table procedure very useful.
Remember that we can put these settings in the login.sql script which will be run automatically whenever we start SQL*Plus. Find out more.
The neat thing about this is, that since 10g, this script is run every time we connect rather just the first time we fire up SQL*Plus...
SQL> conn apc
Enter password:
Connected.
Running login script
Session altered.
SQL> conn scott
Enter password:
Connected.
Running login script
Session altered.
SQL>
I use SQL*Plus exclusively to work with Oracle. Other answers already give some very handy login.sql contents.
This is my login.sql. I copied some suggestions from Tom Kyte and William Robertson in there. Maybe you find some things you want to use as well.
set termout off
set serveroutput on size unlimited
set pagesize 50000
set linesize 135
set long 50000
set trimspool on
set tab off
def _editor = "C:\Progra~1\Notepad++\Notepad++.exe"
define gname=idle
column global_name new_value gname
select lower(user) || '#' ||
substr(global_name,1,decode(dot,0,length(global_name),dot-1)) global_name
from (select global_name,instr(global_name,'.') dot from global_name);
set sqlprompt '&gname> '
alter session set nls_date_format = 'dd-mm-yyyy hh24:mi:ss'
/
var sid number
var serial# number
var tracefile VARCHAR2(200)
DECLARE
v_audsid v$session.audsid%TYPE;
BEGIN
SELECT sid, serial#, audsid
INTO :sid, :serial#, v_audsid
FROM v$session
WHERE audsid = SYS_CONTEXT('USERENV','SESSIONID');
SELECT par.value ||
CASE WHEN par.value LIKE '%/%' THEN '/' ELSE '\' END ||
LOWER(th.instance) ||
'_ora_' || LTRIM(TO_CHAR(pro.spid,'fm99999')) || '.trc' AS filename
INTO :tracefile
FROM v$process pro
, v$session se
, v$parameter par
, v$thread th
WHERE se.audsid = v_audsid
AND pro.addr = se.paddr
AND par.NAME = 'user_dump_dest';
END;
/
BEGIN
IF :sid IS NULL THEN
SELECT sid
INTO :sid
FROM v$mystat
WHERE rownum = 1;
END IF;
END;
/
set termout on
set feedback off
exec DBMS_OUTPUT.PUT_LINE('Sessie: ' || :sid || CASE WHEN :serial# IS NULL THEN ' (no access to V$ tables)' ELSE ',' || :serial# END)
exec IF :tracefile IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE('Eventueel trace-bestand: ' || :tracefile); END IF
prompt
set feedback on
I like to use sqlplus in off-line.
sqlplus -S user/password #query.sql> file.txt
where query.sql is
set feedback off verify off heading off pagesize 0
...here goes a query...
quit;
/
So i can get info from the database in my bat/script files in windows or unix.
I find it is handy to use SQL*Plus column variables within directives - for example, I'm often in a session and want to spool to a new file name to avoid overwriting another log that may already exist and do this (first three statements through an #file):
SQL> column spr new_value spoolref
SQL> select user||'_'||abs(dbms_random.random) spr from dual;
SQL> spool &spoolref
... do work here ...
SQL> spool off
I'll then find the new log by sorting by time - you could always use some strategy other than the random number if you prefer.