The above solution will not work
Vishal, May 05, 2004 - 12:46 pm UTC
Tom, even if a
whenever sqlerror exit 1
statement is added, sqlplus will still exit with a return code of 0, when it is called from within a shell script as part of a variable assignment, as is it is being done in this case.
Instead, in shelfun2.ksh if a test for the return code is done after the call to the shell function, we can achieve the desired results. See the modified shelfun2.ksh below:
#!/bin/ksh
# Name = shelfun2.sh
get_plsql_result()
{
plsql_result=`sqlplus -s scott/tiger <<!
SET SERVEROUTPUT ON FORMAT WRAPPED
SET PAGESIZE 0
SET FEEDBACK OFF
VARIABLE outtext VARCHAR2(250)
BEGIN
:outtext := SUBSTR(scott.pkg.$1,1,250);
EXCEPTION
WHEN OTHERS THEN
:outtext := SUBSTR(SQLERRM,1,250);
END;
/
PRINT :outtext
EXIT
!`
if [ `echo "$plsql_result" | grep '^ORA-[0-9]{5}:' | wc -l` -eq 1 ]
then
echo "$plsql_result"
exit 1
echo "after the error exit"
else
echo "$plsql_result"
echo "after the normal exit"
fi
}
echo "$1"
myvar=`get_plsql_result "$1"`
if [ $? -ne 0 ] # this is the test for the
then # return code from the call
exit 1 # to the shell function.
fi
echo "myvar = "$myvar
echo "here I am after the function call"
exit 0
I hope Tom doesn't mind.
Christo Kutrovsky, June 18, 2004 - 10:37 pm UTC
First of all let me discourage you from using shell scripts to get result from sqlplus. It is a very unsafe way of gething results, you so it yourself with your listing of files been assigned to your variable (which I will explain in a moment).
I would recommend you to use perl for that. I know Tom dislikes perl, but it is far better then a shell script and sqlplus.
I am not sure what is it that you are trying to do, so I am just going to comment on your current issues.
Quote:
Oddly, when the error is raised, get_plsql_result returns "BEGIN" plus the
results of an "ls" on my home directory....?
[end quote]
The reason why you are gething this is because your are not quoting your echo inside your curly braclets:
echo $plsql_result
And when you get an error the assignment is:
BEGIN
*
ERROR at line 1:
ORA-20566: Art's error has been raised
ORA-06512: at line 5
As you can see there's a star there, which get's expanded to all the files in your current directory.
So if you quote it:
echo "$plsql_result"
Also you need to quote the echo itself later:
from:
echo "myvar = "$myvar
to:
echo "myvar = $myvar"
in double quotes, variable expantion occurs.
And then you get the correct result:
kutro-[~]$ shelfun1.ksh error_call
error_call
myvar = BEGIN
*
ERROR at line 1:
ORA-20566: Art's error has been raised
ORA-06512: at line 5
-----------------------
Now to your problem with the return codes. What Tom was suggesting is using the return code of sqlplus, not the printed result of sqlplus.
So I added this:
!`
echo "sqlplus exit code: $?"
echo "$plsql_result"
And re-run:
kutro-[~]$ shelfun1.ksh error_call
error_call
myvar = sqlplus exit code: 0
BEGIN
...
See the exit code is 0.
Now I added:
SET FEEDBACK OFF
whenever sqlerror exit 1
VARIABLE outtext VARCHAR2(250)
And re-run:
kutro-[~]$ shelfun1.ksh error_call
error_call
myvar = sqlplus exit code: 1
BEGIN
Now if you review the documentation about sqlplus you are going to find out that you can use a bind variable thus have your PL/SQL block deside what is the return code !
Another thing I don't understand why do you call so many sub commands with back quotes. I would do it with a global variable ...
Now, back ontrack to what you wanted, here's the result of the modified script:
kutro-[~]$ shelfun1.ksh normal_call
normal_call
SubFunction exit code: 0
myvar = [six]
here I am after the function call
kutro-[~]$ shelfun1.ksh error_call
error_call
SubFunction exit code: 1
And the script itself:
#!/bin/ksh
# Name = shelfun1.ksh
get_plsql_result()
{
plsql_result=`sqlplus -s kutrovsky/me<<!
SET SERVEROUTPUT ON FORMAT WRAPPED
SET PAGESIZE 0
SET FEEDBACK OFF
whenever sqlerror exit 1
VARIABLE outtext VARCHAR2(250)
BEGIN
:outtext := SUBSTR(pkg.$1,1,250);
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
/
PRINT :outtext
EXIT
!`
sqlplus_exit_code=$?
if [[ $sqlplus_exit_code -ne 0 ]] ; then
exit $sqlplus_exit_code
fi
#debug echo "sqlplus exit code: $sqlplus_exit_code"
echo "$plsql_result"
}
echo "$1"
myvar="`get_plsql_result "$1"`"
sub_exit_code=$?
echo "SubFunction exit code: $sub_exit_code"
if [[ $sub_exit_code -ne 0 ]]; then
exit $sub_exit_code
fi
echo "myvar = [$myvar]"
echo
echo "here I am after the function call"
exit 0
--- end ---
Note the extra quoting during the function call.
There is nothing wrong with using a shell to call sqlplus
Eric Worthy, July 08, 2004 - 4:28 pm UTC
I have many many scripts in production
that use korn shell scripts with no problem. No
need to use Perl or anything else.
typeset -i LOG_BATCH_ID=`sqlplus -s <<!!
$ORA_USER/$PASSWD@$ORACLE_SID
set heading off
set feedback off
Select tps_log_batch_id_s.nextval from dual;
!!`
ret_code=$?
oerr=`echo $LOG_BATCH_ID | egrep -ic "ora-|pls-|sp2-"`
if [[ $ret_code -ne 0 || $oerr -ne 0 ]]
then
ERROR=SELECT_ERR_BATCH_ID
echo "$(date '+%H:%M:%S') Error getting log batch id \n" >> $LOGFILE
echo $LOG_BATCH_ID >> $LOGFILE
exit_routine (call the exit function where people get paged,etc..)
fi
July 08, 2004 - 8:42 pm UTC
(i don't like perl at all personally)
Perl?
A reader, July 09, 2004 - 11:43 pm UTC
Would you elaborate on why you dont like Perl? On what grounds? Technical, philosophical, purity, what?
Thanks
July 10, 2004 - 9:15 am UTC
don't like the way it looks, find the code to be very obscure and hard for programmer1 to understand what programmer2 did. most of that is due to lack of comments in the code.
i just don't "like it" - no real technical reason, i don't prevent people from using it, it is just a tool I don't find purpose for myself.
A reader, July 10, 2004 - 10:35 am UTC
Well, it is designed to be a "Swiss Army knife" type of tool, to replace sed, awk, shell, C, C++, etc, etc. So the type of programmers it attracts are typically experienced programmers who are already adept at using the underlying languages. And as such, it is used for quick'n'dirty proof-of-concept implentations that end up lasting for years! Comments, well, as with any language, it is up to the programmer to comment his/her code! The language itself does have a terse and obscure syntax, but really no different than the venerable C language. C can be as terse and hard-to-understand as Perl when used inappropriately.
Personally, I havent found much use for it myself, but I have followed Perl's history and it is quite a fascinating insight into how the open-source model works.
[Actually, Perl is very similar to PHP as far as the "swiss army knife" analogy goes]
Thanks
July 10, 2004 - 8:49 pm UTC
Maybe that is the underlying reason I don't like it, to paraphrase:
o it is used by experienced (lone horse) programmers
o for a quick and dirty prototype (hence just whip it together)
o that goes production "as is"
o with nary a shred of documentation or real design behind it.
Inexpensive, yet overpriced in the long run.
whenever sqlerror question
Yoav, July 03, 2006 - 3:32 pm UTC
Hi Tom,
Im using this code in my transportable tablespace shell
script.
I was trying to stop to program flow, when the exec command
fail, or when the select statment return rows.
I tried to use whenever sqlerror , but it didnt help .
Can i get your advice on that ?
Thanks.
SqlError=1
sqlplus -s /NOLOG<<eof
connect / as sysdba
whenever sqlerror exit $SqlError
exec sys.DBMS_TTS.TRANSPORT_SET_CHECK('TEST', TRUE);
select * from TRANSPORT_SET_VIOLATIONS;
whenever sqlerror exit 0
eof
if [ $SqlError != 0 ]
then
echo " ok"
else
echo " Trasport Violation"
fi
July 07, 2006 - 7:22 pm UTC
use a plsql block...
exec sys.DBMS_TTS.TRANSPORT_SET_CHECK('TEST', TRUE);
REM you want to exit with something NON-ZERO of course!!!
whenever sqlerror exit 1
begin
for x in ( select * from TRANSPORT_SET_VIOLATIONS )
loop
raise PROGRAM_ERROR;
end loop;
end;
/