How to run multiple SQL script files in a Shell script - shell

I have to create 1 UNIX Shell script. In that shell script i want to run multiple SQL script files from the same directory. I have used like this-
#!usr/bin/ksh
SQLPATH = /usr/sql/
(cd $SQLPATH;
'sqlplus usr/password#sid <<EOF
spool <db_file>.log
#<db_name>.sql
set echo off
set heading off
spool off
&&
spool <db_file2>.log
#<db_name2>.sql
set echo off
set heading off
spool off
&&
spool <db_file3>.log
#<db_name3>.sql
set echo off
set heading off
spool off
exit;
EOF')
exit 0
There are multiple SQL scripts like this and for each SQL script I have to create log files so I used spool here. After every SQL script files execute
I used &&. So Is it good to use && here and in 3rd line ; when I define the PATH. Please provide me the better solution.

Don't override the system PATH (or now SQLPATH) and don't put commands in single quotes. Use lowercase for your private variables, and you can't have spaces around the equals sign in an assignment; but a variable you only use once is useless anyway, so I took it out, and hardcoded the cd argument.
I'm guessing you want something like
#!/usr/bin/ksh
# No spaces around equals sign, and don't use uppercase for private variables
# But why use a variable at all anyway
#sqlpath=/usr/sql
cd /usr/sql # is this really necessary and useful??
sqlplus usr/password#sid <<____EOF &&
spool <db_file>.log
#<db_name>.sql
set echo off
set heading off
spool off
____EOF
sqlplus usr/password#sid <<____EOF &&
spool <db_file2>.log
#<db_name2>.sql
set echo off
set heading off
spool off
____EOF
sqlplus usr/password#sid <<____EOF
spool <db_file3>.log
#<db_name3>.sql
set echo off
set heading off
spool off
____EOF
# exit 0 # Not necessary or useful
If the multiple sqlplus commands can be executed in a single session, that would be an obvious improvement; but I'm guessing sqlplus has no way of expressing what you appear to mean with && (this syntax seems to have a quite distinct meaning in sqlplus).

Make a function
#!/usr/bin/ksh
SQLPATH=/usr/sql # Offtopic: Better use lowercase for your own variables
process_sql_and_log() {
if [ $# -ne 2 ]; then
echo "Usage: $0 sqlfile logfile"
return 1
fi
sqlplus usr/password#sid <<EOF
spool ${2}
#${1}
set echo off
set heading off
spool off
exit;
EOF
}
cd "${SQLPATH}" &&
process_sql_and_log db_name.sql db_file.log &&
process_sql_and_log db_name2.sql db_file2.log &&
process_sql_and_log db_name3.sql db_file3.log
exit 0

Related

Not able to overwrite the file properly through unix script

Below the script which I am using to overwrite the chk.sas file but unfortunately it's only overwrite the last statement of code "run;" in chk.sas file.
#!/bin/bash
x=$(pwd)
echo "libname sasdata '$x';" > $x/chk.sas
echo "proc print data=sasdata.data ;" > $x/chk.sas
echo "run;" > $x/chk.sas
sas chk.sas
exit 0
Below is the desired result which I am expecting from the script but I am not sure where I am doing mistake in the script.
libname sasdata '/home/usr' ;
proc print data=sasdata.data ;
run;
Thank you in advance for help.
Each time that > is used, the previous file is overwritten. One solution is to use >> which means append. Another solution is to group all the echo commands together and just use > once:
#!/bin/bash
x=$(pwd)
{
echo "libname sasdata '$x';"
echo "proc print data=sasdata.data ;"
echo "run;"
} > "$x/chk.sas"
sas "$x/chk.sas"
Notes
Unless you specifically want word splitting and pathname expansion, put shell variables inside double quotes. Thus, above, we use "$x/chk.sas" in place of $x/chk.sas.
Use exit 0 if you want the script to return a success exit code even if the sas command failed. If you omit the exit command, the script will exit with the exit code of the last command run (in this case, sas). This is likely more informative for the whatever code invokes the script.
Alternative: here-doc
Another way to write several lines to a file is to use a here-doc:
#!/bin/bash
x=$(pwd)
cat >"$x/chk.sas" <<EOF
libname sasdata '$x';
proc print data=sasdata.data ;
run;
EOF
sas "$x/chk.sas"
For more information, look at the section entitled Here Documents in man bash.

For loop executes twice, not sure how to fix

I have written a shell script. The for loop runs twice. Not sure how to fix this.
Can any one please assist me in resolving the issue?
Code:
#!/bin/sh
mkdir -p C:/Users/spatro/Desktop/attachment_backup
feed=`sqlplus -s <<EOF
$1/$2
whenever sqlerror exit sql.sqlcode rollback
SET SERVEROUTPUT ON
SET VERIFY OFF
SET FEEDBACK OFF
SET HEADING OFF
SET PAGESIZE 0
select attach_sub_folder from DC_Purge_Files_log where entity_type = 'Attachment' and delete_complete = 'N';
/
exit
EOF`
for counter in $feed
do
mkdir -p C:/Users/spatro/Desktop/attachment_backup/$counter
echo "Sub folder created "$counter
done
Rule number one of safe shellscripting: Always use quotes
Your loop would have executed once, had the command substitution (the stuff in backticks) and $feed variable been quoted. As it stands, those are asking for trouble! Specifically, word splitting and glob expansion.
If you would like some tooling:
Shellcheck would answer your question, and Naziquote would fix it (see this question).
If you want the for loop to execute just once, use a break statement before "done"
for counter in $feed
do
mkdir -p C:/Users/spatro/Desktop/attachment_backup/$counter
echo "Sub folder created "$counter
break
done

How to break loop in shell script used to truncate table?

I'm writing a script truncating tables. The problem is that the script goes in infinite loop.
./n_input contains environment variables that are used in script.
#!/bin/ksh
INPUT_FILE=./n_input
if [ ! -e $INPUT_FILE ];
then
echo "Error: Input file require"
exit 1
fi
source $INPUT_FILE
while read Table
do
TABLE="$DSTN_DATABASE.dbo.$Table"
echo "Table : $TABLE"
QUERY="truncate table $TABLE"
echo $QUERY > ./tmp_file
sqlcmd -m 1 -U $DSTN_USER -P $DSTN_PASSWORD -D -S $DSTN_SERVER -m1 -i ./tmp_file
RET_VALUE=$?
if [ $RET_VALUE -ne 0 ]
then
echo "Error $TABLE"
fi
done < $TABLE_LIST
exit 0
How do I break the loop? I have tried to remove sqlcmd from script and verified that it was working. It's working as expected. Observed the same behavior with sqlcmd -Q option.
$TABLE_LIST file contains only one table name.
You don't need to write the query into temporary file. Use -q, or -Q options instead:
q="truncate table ${TABLE};"
sqlcmd -m 1 -U "$DSTN_USER" -P "$DSTN_PASSWORD" -S "$DSTN_SERVER" -q "$q"
Note the ; at the end of the query. Probably, that's the reason why the script "stalls". That may look like an infinitely running loop.
Also note the use of double quotes. You should wrap variables in double quotes to prevent reinterpretation of the special characters.
By the way, you can locate the exact command that is causing the issue by adding set -x at the beginning of the script. set -x turns on debugging mode. With debugging mode on, you see the commands being executed.
It's very unlikely that the content of $TABLE_LIST file is causing such behavior, unless the file is enormously big. The loop construct is correct, and the number of iterations should match the number of lines in the file.

How to SET LINESIZE ORACLE with echo

Hello dear stackoverflowers,
I am writing a shell script in which I need to dump a sqlplus database content in a file, I need to have it done in one command line.
echo 'SET LINESIZE 1000; select * from myDb;'| sqlplus -S user/pass#host
But I get
SP2-0268: linesize option not a valid number
I tried without ';' but I have the same result.
I couldn't find any example here or elsewhere on how to do this.
Any help on that?
Thanks!
echo 'SET LINESIZE 1000\n select * from myDb;' |sed 's/\\n/\n/' |sqlplus -S user/pass#host

getting syntax error at line 34 : `<<' unmatched in ksh script

I have a shell script, when I execute it, I get the error
syntax error at line 34 : `<<' unmatched in ksh script
column_name=`sqlplus -s $BASE_DB_CONN<<!!
WHENEVER SQLERROR exit ROLLBACK
set SQLPROMPT ''
set heading off
set pagesize 1000
set linesize 5000
set feedback off
set define on
set verify off
#smm9_stream_map.sql $STREAM_NAME $FIELD_NAME"
exit
!!`;
To my surprise the same thing works in the while loop altered script as below
while [ $a -lt ${NO_LOOP} ]
do
column_name=`sqlplus -s $BASE_DB_CONN<<!!
WHENEVER SQLERROR exit ROLLBACK
set SQLPROMPT ''
set heading off
set pagesize 1000
set linesize 5000
set feedback off
set define on
set verify off
#smm9_stream_map.sql $STREAM_NAME $FIELD_NAME"
exit
!!`;
a=`expr $a + 1`
done
Why does the second script work but not the first one?
The heredoc terminator must be the only text on that line, no other whitespace allowed (*)
column_name=$(sqlplus -s $BASE_DB_CONN<<!!
....
exit
!!
)
(*) the exception being, for heredocs using <<-, any leading tabs will be stripped from the heredoc, including from the terminator. I see in my ksh93 man page:
If # is appended to <<, then leading spaces and tabs will be
stripped off the first line of the document and up to an equivalent indentation will be
stripped from the remaining lines and from word.

Resources