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.
Related
I am trying to run a basic shell script to query my Oracle database and give me back results with a pipe | delimiter versus a comma.
No matter what I try it only returns with commas. Any help would be appreciated.
#!/bin/bash
sqlplus -s $DBUSER/$DBPASS#$DBCONN/$DBSID <<EOF
set colsep '|'
set echo off
#$SCRIPT_PATH/QRY_1.SQL
exit;
EOF
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
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
I can't find any documentation indicating that this is correct behavior. I've verified this behavior on bash 4.2.25 and 4.1.2. Those are the latest to which I have simple access.
Much appreciated if anybody has an explanation for why the conditional changes the behavior of the preceding subshell.
# ( set -e; false ; echo bye )
# ( set -e; false ; echo bye ) || echo "failed"
bye
#
thanks,
Brian
See the the following link
The -e setting shall be ignored when executing the compound
list following the while, until, if, or elif reserved word,
a pipeline beginning with the ! reserved word, or any
command of an AND-OR list other than the last.
I believe the emphasized portion of the description of the -e option in the bash 4.2 man page applies:
The shell does not exit if
the command that fails is [...] part of any command executed in
a && or || list [...]
The false command is part of the subshell which makes up the LHS of the || operator, so although it fails, the -e is ignored. Arguably, this is a bug, since false is not part of an || in the shell where set -e is actually set.
while IFS=# read -r process_id source destination type
do
echo "Process id: $process_id"
echo "Source: $source"
echo "Destination: $destination"
case "$type" in
2)
echo "Type is outbound: $type"
contact=$(sqlplus -s ${SQLPLUS_INFO} <<EOF
SET PAGESIZE 0
SELECT email FROM table WHERE partner = '${destination}';
exit
EOF
)
echo
echo ${contact}
echo
;;
Based in the code above, how can I pass the value from $destination to the query? The example above is not working, even these other ones:
SELECT email FROM table WHERE partner = '"${destination}"';
SELECT email FROM table WHERE partner = '$destination';
What happens when you run the script with bash -x? I ask because the here-document notation expects to find the end marker at the start of a line. When I run this code:
#!/bin/bash
contact=$(cat - <<EOF
input from here document
second line
EOF
)
echo "$contact"
I get errors like:
eof.sh: line 3: unexpected EOF while looking for matching `)'
eof.sh: line 10: syntax error: unexpected end of file
If the lines start with tabs, you can use a dash before the end-of-file marker to indicate that leading tabs should be ignored.
#!/bin/bash
contact=$(cat - <<-EOF
input from here document
second line
EOF
)
echo "$contact"
This outputs:
input from here document
second line
Replace those tabs with blanks and you are back into the syntax errors. Although I've couched this in terms of bash, I believe you run into the same issues with Korn and Bourne shells too.
So, my suspicion is that your problem is related to the formatting of the here-document in your code, but you should have been seeing some sort of error, so I'm a bit puzzled. You should be getting the substitutions you wanted made:
#!/bin/bash
description="The Description"
contact=$(cat - <<-EOF
input from here document
second line with '$description' embedded.
EOF
)
echo "$contact"
This yields:
input from here document
second line with 'The Description' embedded.
Using bash -x can be helpful to trace the execution of a command.
All of this is only coincidentally related to Oracle and SQL*Plus.
Please try to remove the single quotes around your variable: they prevent your variable to be interpreted (contrary to double quotes).
That should be:
SELECT email FROM table WHERE partner = ${destination};