Sqlplus printing the result twice and with an empty line - oracle

I write shell script and want to use sqlplus, when I write:
#!/bin/bash
result=$(sqlplus -s user/pass#DB << EOF
set trimspool on;
set linesize 32000;
SET SPACE 0;
SELECT MAX(DNNCMNT_ANSWER_TIME) FROM TKIMEI.DNNCMNT_IMEI_APPRV;
/
exit;
EOF)
echo "$result"
the result is in txt file (I'm executing it as ksh sql.sh > result.txt):
MAX(DNNCM
---------
10-MAR-14
MAX(DNNCM
---------
10-MAR-14
it is automatically putting an empty line at the beginning of file and writing the result twice.
How can I fix it ?

Remove the slash. It's causing the previous command (the select) to be repeated:
http://docs.oracle.com/cd/B10501_01/server.920/a90842/ch13.htm#1006932
Also, talk to your DBA about setting up external OS authentication so you don't have to hardcode the password in a shell script for security reasons. Once set up, you can replace the login/password combo with just a slash:
http://docs.oracle.com/cd/E25054_01/network.1111/e16543/authentication.htm#i1007520

Related

Must run a SQLPlus query in bat file, can't get query to append the query results a txt file using the .BAT file

I know this is something minor I'm screwing up. I didn't write the SQL -it's as is - just the .BAT file. I have to run it using a .BAT file as there's more stuff that happens afterwards.
I have a query. It's supposed to insert a bunch of values from different tables into a temp table, then return all four fields separated by commas, and no header row. It works like it's supposed to. I tried to anonymize it, so it might look weird.
SQL File Name: c:\Directory\BA_ExportAll.sql
THESE TWO LINES are at the top of the query and I don't know why they aren't properly appearing to be in the sql query itself.
START /data/admin/connect.sql
START today.sql
INSERT INTO
My_Table_TMP
SELECT
'A',
'Sequence',
AUX.P_ID,
NULL
FROM
(
SELECT
P_ID
FROM
Table1
WHERE
feedDate = (SELECT MAX(feedDate) FROM Table1)
MINUS
SELECT
P_ID
FROM
Table2
WHERE
objstate NOT LIke 'C%'
) AUX
;
--Then a bunch of other queries that build the temp table
COMMIT;
SET COLSEP ''
SET SPACE 0
SET LIN 150
SET PAGES 0
SET VERIFY OFF
SET FEEDBACK OFF
SET ECHO OFF;
COLUMN Value FORMAT A11
SPOOL segment_after.&today
SELECT
flag || ',',
segment || ',',
value || ',' as value,
'"' || description || '"'
FROM
My_Table_TMP
;
SPOOL OFF;
EXIT;
So far, so good.
Now, the .BAT file.
cd C:\Directory\
sqlplus /nolog #BA_ExportAll.sql
ECHO c:\Directory\BA_ExportAll.sql >> "c:\Directory\BA_HeaderTest.txt"
The .BAT file will eventually kick off an email script and some other stuff.
This just appends the actual line "c:\Directory\BA_ExportAll.sql" into the "c:\Directory\BA_HeaderTest.txt" text file. I have googled and checked here, obviously, over and over and can't find any similar questions. I'm assuming it's completely simple!!
Thanks, all!
sqlplus /nolog #BA_ExportAll.sql >> "c:\Directory\BA_HeaderTest.txt"
should append any console output to the text file.
Your echo line merely appends the literal c:\Directory\BA_ExportAll.sql to the text file
TYPE c:\Directory\BA_ExportAll.sql >> "c:\Directory\BA_HeaderTest.txt"
would append the contents of the .sql file to the .txt file.
To skip a number of lines of the sqlplus output, try
(
for /f "skip=ndelims=" %%b in ('sqlplus /nolog #BA_ExportAll.sql') do echo %%b
)>> "c:\Directory\BA_HeaderTest.txt"
Placing parentheses around a command buffers the output so the file is not perpetually opened and closed (I believe).
for /f reads the output of the command in quotes line-by-line. It has many options - see for /? from the prompt and many, many applications on SO for documentation & ideas. The delims= option causes all of the line to be applied to token 1 and appears in %%b. The skip=n option skips the initial n lines.
If I understood you correctly, you'd like to append result of that SELECT statement into a file which already contains some data.
If that's so, then it is the SPOOL command you should modify (the last ECHO won't do any good):
SPOOL segment_after.&today APPEND
i.e.
...
SET FEEDBACK OFF
SET ECHO OFF;
COLUMN Value FORMAT A11
SPOOL segment_after.&today APPEND
SELECT ...
FROM ...;
SPOOL OFF;
EXIT;

Spooling to a file with a name containing a space and script's parameter in sqlplus?

I'm trying to change a script with a parameter to spool the output into specific path. After searching Stack Overflow I came up with:
column filename new_val filename
select '"i:\Direct bank\incoming\ROSE\report_zgod_' || '^1' ||'.csv"' filename from dual;
spool &filename
This creates correct filename "i:\Direct bank\incoming\ROSE\report_zgod_2017-08-28.csv" (I have tried to put it literally instead of &filename and the file has been created), but it still does not write a file. My guess is that's because there is a space in the path.
I have also tried
spool "&filename"
spool '&filename'
but to no avail.
I can't avoid parameter (it's used in other places in script and it can't be really calculated from SYSDATE) and I can't change the path (it has to be somewhere under "I:\Direct bank").
How can I have both the parameter and the space in spool file's name?
OK, I found the answer in comments to https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:3581757800346555562 .
The author of the original script has changed the defaults, so that I have to use
spool ^filename
instead of
spool &filename
In case you have similar problem, the orginal code contained:
set define "^"
set sqlprefix "^"
And that was the reason I could not get the file created.
When the path has a space in it then try using the short form of the path name. So, to SPOOL to /opt/oracle/oradata/Custom Scripts/orders_between_dates.txt; it's...
SQL> SPOOL /opt/oracle/oradata/Custom~1/orders_between_dates.txt;
If you're running it from a .sql script then put "" around it, like this...
SET FEEDBACK OFF;
SET MARKUP CSV ON;
SET VERIFY OFF;
SPOOL "/opt/oracle/oradata/Custom~1/orders_between_dates.txt"
SELECT * FROM orders_detail WHERE order_date BETWEEN '&1' AND '&2';
SPOOL OFF;
EXIT;
The command to run this script for a rolling seven day window would be something like...
> sqlplus ot/Orcl1234#xepdb1 #"/opt/oracle/oradata/Custom Scripts/orders_between_dates.sql" $(date +%d-%b-%Y -d '-7 days') $(date +%d-%b-%Y)

How to spool file1 or file2 from a single SQL file based on the input?

I have a SQL file like the following:
SET ECHO OFF
set feed off
set verify off
set head off
set pagesize 0
set space 0
set trimspool on
set line 250
spool subir.rpt
select 'Subir' from dual;
spool off
SET ECHO OFF
set feed off
set verify off
set head off
set pagesize 0
set space 0
set trimspool on
set line 250
spool vishal.rpt
select 'vishal' from dual;
spool off
Let's call this file spool.sql. I need to enable creation of spool file based on the input spool.sql file receives. For example, if it receives "subir.rpt" The first portion of the SQL file should run and subir.rpt should be produced; if it is vishal.rpt, the second portion should run and vishal.rpt should get generated.
How can this be achieved?
Edit: This SQL file is getting called from a shell script. The shellscript is like the following:
sqlplus -s dbread$HOST_CONNECT_STR/dbread<<endplus
#spool.sql
endplus
What is launching this spool.sql? A shell script? Database function?
If it's a shell script, I would either use a parameter to this script or split it into two separate .sql files and call the appropriate one.
You could also save the file value into a temporary table prior to calling this script and select it before spooling the file.
There are a lot of options but it all depends on how you call this script and how extensible you want it to be.
The simplest way would be to use the supplied parameter dynamically as the spoolfile:
set echo off
set feed off
set verify off
set head off
set pagesize 0
set space 0
set trimspool on
set line 250
spool &1
spool
select 'Subir' from dual where '&1' = 'Subir.rpt';
select 'vishal' from dual where '&1' = 'vishal.rpt';
spool off
(The spool command on its own is just to print the current spoolfile name for demo purposes.)

remove blank lines from csv using shell script for oracle

Hi am using following shell script to create csv from oracle database
export ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
export PATH=$PATH:$ORACLE_HOME/bin
sqlplus -s user1/user1<<!
Spool on
set heading off
SET FEEDBACK OFF
set wrap off
set colsep ,
SET LINESIZE 200
set trims on
Spool /home/ist/username.csv
select 'username','userid' from dual;
select username,userid from users;
Spool off
EXIT
!
I am getting following output
as you can see there is blank line at first and third row
but am expecting file without blank lines.
Any help will be appreciated.
Use the
SET PAGESIZE 0
command to avoid the blank lines. this also suppresses column headings, so you can remove
SET HEADING OFF
The command
SPOOL on
does not make sense because it starts spooling in a file named on.lst. So remove this command, too.
If you want to display the heading with the column name
you can try the following settings
set HEADING ON
SET FEEDBACK OFF
set WRAP OFF
set COLSEP ,
SET LINESIZE 32767
set NEWPAGE none
set UNDERLINE OFF
set TRIMSPOOL ON
set TRIMOUT ON
set PAGESIZE 50000
´heading on´ is the default so you must not set it. It enables the display of the column names when a select starts. underline off suppresses the '---' line between column names and data of a select. pages 50000 sets the pagesize to its maximum value (Oracle 11.2). linesize 32767 sets the linesize to its maximum value (Oracle 11.2). newpage none is necessary to suppress this empty line at the beginning of a page that was the primary concern of your posting.
All this can be found in the SQL*Plus Command Reference
The termout off parameter suppresses only output created by a scripts that is executed with the # or ## command. It dos not suppress out by a command entered in the SQL*plus console. If you use
sqlplus user/passw#connect <<!
...
!
you use the here-document syntax of the shell language which simulates the interactive input. So put your sql commands in a script, e.g. script.sql, and execute
sqlplus user/passw#connect #script.sql
then termout off will suppress terminal output.
Instead of
colsep ,
select username,userid
...
which returns something like
user1 , 14
nextuser , 236
myuser , 11
...
you can use leave the COLSEP unchanged and execute
select username||','||userid
...
to get the following output
user1,14
nextuser,236
myuser,11
...
Maybe this is useful
https://dba.stackexchange.com/a/64620/2047
set trimspool on
this will work for you
put this on your script
sed -i '/^\s*$/d'/home/ist/username.csv
Remove lines in /home/ist/username.csv without a , using
grep "," /home/ist/username.csv > /home/ist/username2.csv
# or
sed -i '/^[^,]*$/ d' /home/ist/username.csv
SQLPLUS 12.2 has an feature to output CSV, but you need to configure some settings to remove blank lines on it. Here is my approach
SET HEADING OFF;
SET PAGES 0;
SET SQLBLANKLINES ON;
set echo off;
set autotrace off;
set feedback off;
SET TRIM ON;
SET MARKUP CSV ON DELIMITER | QUOTE OFF;

Need to pass string with newline character from Unix shell script to sql query

I am using unix shell KSH scripting to do some table cleanup.
I have a file "partner.txt" with 5000 line like this
>cat partner.txt
aaa0000
aaa0001
aaa0002
...
...
aaa5000
Using this file, I am supposed to clean few tables with matching, say agreements of the partners.
So i am constructing a partner list string in the format that i can use in the sql statement with 'IN' clause (select * from tab where partner IN partner_list)
('aaa0000',
'aaa0001','aaa0002',...,'aaa0010',
'aaa0011','aaa0012',...,'aaa0020',
...
'aaa4990','aaa4991',...,'aaa5000')
I am assigning the string to partner_list variable like this.
export BO="("
export BC=")"
export BQ="('"
export QC="','"
export QB="')"
export C=","
export CE=","'\n'
export QCE="',"'\n'"'"
partnerListLine=${BO}
while read partnerline;
do
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}${CE}
elif [ ${counter} -lt ${numOfObsoletePartner} ]
then
partnerListLine=${partnerListLine}${partnerline}${C}
fi
counter=`expr ${counter} + 1`
done < partner.txt
partnerListLine=${partnerListLine}${partnerline}${BC}
Then I am using this partner list to fetch my agreement list like
SQL_agreement='select distinct a.agreement from partner_agreement_map a where a.partner in ${partner_list} order by agreement asc;'
I needed the newline character in my partner list since i was using sqlplus and was encountering SP2-0027: Input is too long (> 2499 characters)
I am adding the newline character by appending the below to my partner list string after N partners
CE=","'\n'
This worked fine when i was using sqlplus directly in the script.
But when i try to pass this partner_list string as parameter to a sql script, it shows '\n' in the query.
This is how i call my sql script and pass the parameter
sqlplus -s ${REFERENCE_DB_USER}/${REFERENCE_DB_PASS}#${DATABASE_INSTANCE} << !!
set serveroutput on size 10000;
set feedback off;
set verify off;
set echo off;
set term off;
set pagesize 0;
SET linesize 1000;
SET TRIMSPOOL ON;
spool 1_del_agreement_spool_$$.lst;
#1_del_agreement.sql ${partner_list};
spool off;
exit;
/
!!
this is my spooled file
>cat 1_del_agreement_spool_18165.lst <
select distinct a.agreement from partner_agreement_map a where a.partner in ('aaa0000',\n'aaa0001','aaa0002','aaa0003',...'aaa0010',\n'aaa0011'...) order by agreement asc
*
ERROR at line 1:
ORA-00907: missing right parenthesis
How can i maintain the newline character when i pass the parameter to the sql script and not have it replaced to '\n'?
I have tried ANSI-C quoting but failed.
Please let me know if you would need more details of the shell or sql script
UPDATED MY ENTIRE SOLUTION DESIGN
After trying all night, i have given up.
Thanks Aaron and mplf for your inputs.
I have decided to change my solution from file based to table based. I will be reading the partner.txt file and inserting the partners in a dummy temporary table. Then I can formulate queries with ease on other tables.
In fact, i think this should have been my first design :) There may be something very minor that i was missing in the previous design. But anyways, this will be much easier
I wish my team lead ever reviews design rather than code formatting issues :P
If you are using bash you can use $'\n' to print a newline character which would make your example
if [ `expr ${counter} % 10` -eq 0 ]
then
partnerListLine=${partnerListLine}${partnerline}"',"$'\n'"'"
else
...
Example:
$ echo hello"',"$'\n'"'"
hello',
'
I don't have a working solution but a hint: '\n' means "insert the literal backslash followed by n". So you tell the shell to leave this string alone.
Try NL=$(echo -e '\n') or similar to get a string variable which actually contains a newline. Then you can define CE=",$NL"
The shell might preserve this new line character as it processes the string.
Or use a tool like awk to create a string value with newlines which you assign to partner_list with partner_list=$(awk ...) to prevent the shell from doing any kind of processing of the value.
If that doesn't work, you may have to write the data to a file (with new lines).

Resources