sqlplus removes extra whitespace - bash

I have a below test ksh file
#!/bin/ksh
(
sqlplus -s << EOF
${DATABASE}
SET SERVEROUTPUT ON;
SET HEAD OFF
SET FEED OFF
SET DEFINE OFF
SET PAGES 0
SET COLSEP ";"
WHENEVER SQLERROR EXIT SQL.SQLCODE
SELECT 'aaaa vvvv cccc' FROM DUAL;
EXIT
EOF
) | while read sql_out
do
echo ${sql_out}
done
The expected output is
aaaa vvvv cccc
however the output observed is
aaaa vvvv cccc
Sqlplus is stripping out extra white spaces from my output and I want to preserve it.

It isn't SQL*Plus doing that, it's the shell. You need to enclose your variable in quotes:
To preserve whitespace within a string or in a variable, use quoting.
So instead of
echo ${sql_out}
do either of these:
echo "${sql_out}"
printf "%s\n" "${sql_out}"
and the output will then be:
aaaa vvvv cccc

Related

Why a new line character appending to shell variable?

I have used the method to assign the SQL output to a variable as below.
dbRole=$(${SQLPLUSPGM} -s / as sysdba <<-EOF
set head off
set verify off
set feedback off
select trim(translate(database_role,' ','_')) from v\$database;
exit;
EOF
)
But the variable o/p appending a "\n" character i.e \nPHYSICAL_STANDBY
However, when I use the below method it is working fine
${SQLPLUSPGM} -s / as sysdba <<-EOF | grep -v '^$' | read dbRole
set head off
set verify off
set feedback off
select trim(translate(database_role,' ','_')) from v\$database;
exit;
EOF
Any suggestion why it is appending `\n' and how we can get rid of it.
Appreciate your suggestions.
Your second method, with the grep -v, removes the additional line.
You can use some filter inside your first method with additional parentheses.
dbRole=$((cat | grep -v "^$") <<-EOF
1
2
3
5
EOF
)
Alternative filters with some differences are grep ., head -1, sed '$d'.

set escape on then issue host command in SQL*Plus

The command set escape on would enable the escape character.
SQL> select '\&' from dual;
'
-
&
SQL>
But when issue a host command, I can't understand the behavior.
SQL> host echo foobar aa
foobar aa
SQL> show escape
escape "\" (hex 5c)
SQL> host echo foobar \&
foobar
SQL> host echo foobar '\&'
foobar &
SQL>
Why does using '\&' instead of just \& change the output?
& is a substitution character
The & is translated as this and is just waiting for more (translated into nothing).
SQL> host echo &
SP2-0317: expected symbol name is missing
SQL> host echo 1
1
<- One line returns
SQL> host echo \&
<- two lines return
SQL> host echo 1 & 2
Enter value for 2: 3
1 3

Bash ending the variable after first space?

I'm building a string in Bash in a loop. The data processed by the loop from the lines in two files which are looking like this:
FIRST part of the string is a line in file 1 looking like:
SOME_PACKAGE
SECOND PART is a line of a file 2 looking like:
someFunction('some',parameters,here)
The final output has a dot between the two strings:
1 SOME_PACKAGE.someFunction('some',parameters,here)
The 1 is important here. Explaination in a second.
The string is formed in a double while loop
while read line1 ; do
while read line2 ; do
stringArray=($line2)
string=$line1.${stringArray[1]}
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
connect user/password#db_instance
variable rc refcursor;
SPOOL ${line1}_${stringArray[0]}.DATA
exec :rc := $string;
print rc;
spool off
exit
EOF
done < file2.txt
done < file1.txt
This string is then passed to SQLPlus, and SQLPlus should exit a command like this:
SQL> variable rc refcursor;
SQL> exec :rc := SOME_PACKAGE.someFunction('some',parameters,here);
SQL> print rc;
Until now, everything was working fine. But I got a more complicated parameters next to the someFunction. Now it looks like this:
SOME_PACKAGE.someFunction('some',parameters,here,'and 2 more',NULL)
It seems that the variable passed to SQL*Plus ends on the first space... So it looks like:
SOME_PACKAGE.someFunction('some',parameters,here,'and
From what I know I shouldnt pass spaces in variables, or if I want to do this, I should wrap them in quote signs: "" but where should I put those quote signs to pass the final vatiable to SQL*Plus WITHOUT those quote signs? Or what other solution do You guys propose?
The answer was simple thanks to #arco444.
The reason all this happened was the Internal field separator, which was set to default.
What I did was the following:
I've changed the look of file2 from
1 SOME_PACKAGE.someFunction('some',parameters,here,'and 2 more',NULL)
to
1§SOME_PACKAGE.someFunction('some',parameters,here,'and 2 more',NULL)
And I added some ILS changes before and after the loop, so the final code looks like this:
oldifs=$IFS
IFS="§"
while read line1 ; do
while read line2 ; do
stringArray=($line2)
string=$line1.${stringArray[1]}
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
connect user/password#db_instance
variable rc refcursor;
SPOOL ${line1}_${stringArray[0]}.DATA
exec :rc := $string;
print rc;
spool off
exit
EOF
done < file2.txt
done < file1.txt
IFS=$oldifs
Everything is working like a charm now.

line 45: syntax error: unexpected end of file

When I try running the script, I am gettin the error line 45: syntax error: unexpected end of file. I am relatively new to scripting. Please help me resolve it.
#!/bin/ksh
set -xv
export HOME=/home/mine
. $HOME/.env.ksh
BIS_SPOOL=/tmp/bis_table_mine.spl
BIS_REPORT_MINE=/tmp/bis_table_report_mine.txt
touch $BIS_SPOOL
rm $BIS_SPOOL
touch $BIS_SPOOL
exec 5< $BIS_REPORT_MINE
while read -u5 REC_MINE
do
TBLENAME=`echo "$REC_MINE" | awk '{print $3}' | tr '[:upper:]' '[:lower:]'`
sqlplus -s ${USER_ID}/${USER_PASS}#${ORACLE_SID} <<- EOF
set feedback off
set hea ON
set pagesize 9999
set linesize 9999
set trimspool ON
set termout off
spool $BIS_SPOOL append
Column C1 Heading 'Job Name' Format a30
Column C2 Heading 'Table Name' Format a30
SELECT job_name C1,
table_name C2,
FROM table_usage
WHERE table_name like 'TBLENAME%'
/
exit;
EOF
done
exec 5<& -
The <<- EOS is interpreted literally. Make it
sqlplus -s ${USER_ID}/${USER_PASS}#${ORACLE_SID} <<-EOF
without the space char.
Also make sure there is no space char before or after your closing EOS , but leading tab chars are allowed.
IHTH

ORACLE: need to export table data without spaces between columns

Say i have Table A with columns
col1 col2 col3 col4
-------------------
sajal singh 28 IND
hello how are you
I want to export the data into a flat file without spaces or tabs between columns
So the output should be
cat dump
sajalsingh28IND
hellohowareyou
what i have tried. i have written a script
#!/usr/bin/bash
#the file where sql output will go
OUT=report.txt
>$OUT
DESC=desc.txt
>$DESC
sqlplus -s "xxx/xxx#xxx" << END_SQL > /dev/null
set pages 0
set feedback off
set heading off
set trimspool off
set termout off
set verify off
set wrap off
SPOOL $DESC
Select * from table_name;
SPOOL OFF
END_SQL
But i am getting outputs of one row in multiple lines and with tabs/spaces
So question is how can i fix that? and
I found some data pump utilities like expdp. Can i use that in Unix? if yes, how can i acheive the dump in that format?
Thank You
If you already have a CSV dump, then you can run the following command:
awk 'BEGIN{FS=",";OFS=""}{$1=$1}1' csv.dump > new.dump
Untested:
SET HEADING OFF
SET FEEDBACK OFF
SPOOL $DESC
SELECT col1 ||''|| col2 ||''|| col3 FROM table_name;
SPOOL OFF;
From a "simplified oracle view" to "plain" characters with sed:
sed -n '3,$ s/\s//gp' file
$cat file
col1 col2 col3 col4
-------------------
sajal singh 28 IND
hello how are you
$sed -n '3,$ s/\s//gp' file
sajalsingh28IND
hellohowareyou
Explanation: replace all white space (not line breaks) from line 3 to EOF with "nothing".
If you want the columns padded out but no additional spaces between the columns you can do:
set colsep ""
The default is to have a single space between the double-quotes, which puts a single space between the columns. You might also want to do:
set tab off
... to ensure that multiple spaces in the padding isn't converted to tabs, which looks fine for display but would be a pain parsing the file.
If you want no spaces at all, to do this within SQL*Plus you'd need to concatenate the columns:
select col1 || col2 || col3 || col4 from table_name;
This is useful if you're putting a delimiter between the columns (e.g. making it a CSV), but I don't know what you'd be able to do with the data in the file if you squashed everything together without delimiters.
So this is what i came up with: it will dump oracle data without any spaces etc between columns, while preserving the spaces within data. I thought i would share it with you.
#!/usr/bin/bash
#the file where sql output will go
OUT=report.txt
>$OUT
DESC=desc.txt
>$DESC
TABLE_NAME=$1
###GET DESCRIBE####
s=""
#######################
sqlplus -s "xxx/xxx#xxx" << END_SQL > /dev/null
set pages 0
set feedback off
set heading off
set trimspool off
set termout off
set verify off
set wrap off
SPOOL $DESC
desc $TABLE_NAME;
SPOOL OFF
END_SQL
#######################
for i in `cat $DESC|awk -F" " '{print $1}'|grep -v -i name|grep -v -`
do
s=$s"trim($i)||'|'||"
done
s=`echo $s|sed "s/||'|'||$//g"`
echo $s
#######################
#sqlplus - silent mode
#redirect /dev/null so that output is not shown on terminal
sqlplus -s "xxx/xxx#xxx" << END_SQL > /dev/null
set pages 0
set feedback off
set heading off
set trimspool off
set termout off
set verify off
set colsep ""
set tab off
set lines 1500
SPOOL $OUT
select $s from $TABLE_NAME;
SPOOL OFF
END_SQL
#######################
cat $OUT|sed "s/|//g"|sed "s/ *$//g" >$OUT.new
mv $OUT.new $OUT
echo Finished writing report $OUT

Resources