I want to know how to write a shell script that access oracle database and check a procedure that executed earlier if it is succeeded or returned error
If you want to know about procedure that executed earlier (in a different session?), you can't, unless the results were persisted somehow. Oracle by itself doesn't store info about every procedure call.
If you just want to run and check the stored procedure immediately from the shell script, that's a standard pattern, use whenever sqlerror/oserror clause:
sqlplus [connection_string] <<-EOF
whenever oserror exit failure;
whenever sqlerror exit failure;
exec [stored_procedure];
EOF
if [[ $? != 0 ]]; then
echo "Procedure failed!"
exit 1
fi
->Reference
Related
I am using DB2 11.5.
I have a stored procedure that will run some complex tasks.
Before running the tasks, it will first check from a log table if the job is already running, if yes, it signal for SQLSTATE 75002 with error meesage.
If it is not already running, it will insert a record of the job with status RUNNING, then run the tasks.
When it finishes, it update the status to FINISHED.
CREATE OR REPLACE PROCEDURE WORK.TEST_SP()
P1: BEGIN
if exists(select 1 from db2inst1.job_log where job='abc' and status='RUNNING' and date=current date) then
SIGNAL SQLSTATE '75002' SET MESSAGE_TEXT = 'Job abc is already running, please wait for it to finish';
end if;
insert into db2inst1.job_log values ('abc', 'RUNNING', current date);
commit;
-- Some complex tasks here
call dbms_lock.sleep(120);
update db2inst1.job_log set job_status='FINISHED' where job_name='abc' and job_date=current date
commit;
END P1
My question is how do I handle sigint when user press ctrl-c that aborted the stored procedure when the complex tasks are running?
I want it to update the job_status to ABORTED when ctrl-c occurs so that the job will not be "running" forever.
#Edit 1
Users run the stored procedure with a windows .bat file on local machine with db2 client installed.
#echo off
#if ""%DB2CLP%""=="""" db2cmd /c /i /w ""%0"" && goto :EOF
db2 connect to mydb user db2inst1 using abc123
db2 "call WORK.TEST_SP()"
IF ERRORLEVEL 1 (echo Job failed) else (echo Job done)
db2 connect reset > nul
pause
If your MS-Windows batch file gets interrupted by a Control-C or other signal, then any already started/running stored-procedures invoked by that app will continue running by default. The stored procedure will be unaware that the client application has terminated. So your batch file (cmd/bat) will terminate but any currently running stored procedure will continue to execute on the Db2-server.
You cannot send operating-system signals directly to a Db2-LUW stored procedure, as they run on the Db2-server in the background and are usually owned by a different account than the userid performing the call.
Your stored-procedure should have its own condition handlers or exit handlers or undo handlers. Usually you want to issue a rollback if a hard error happens from which your procedure itself cannot recover. But Db2 itself will issue a rollback for specific sqlcodes (e.g. -911 ).
Db2-LUW also has a sysproc.cancel_work procedure which an application might use in specific situations. Refer to the Knowledge Centre for details. If WLM (workload management) or equivalent is enabled then stored procedures are subject to its configuration as regards resource consumption, and WLM also offers a wlm_cancel_activity routine.
There is no way to do this in SP.
Control is not passed to an exception handler defined in SP upon forcing a caller off the database, canceling activity and some other conditions (log full, for example).
So, don't put any flag / status management logic into SP exception handlers.
How is the stored procedure run? From the command line (db2)? If so, on what operating systems?
If, for instance, the command is run from bash on Linux, you can use trap myfunc SIGINT in Bash to run a custom Bash function myfunc if the user presses Ctrl-C. myfunc could then change the job status.
On Windows, you will have more control if you switch from plain .bat files to Powershell . Some related Stack Overflow questions:
batch script if user press Ctrl+C do a command before exiting
Gracefully stopping in Powershell
how to declare variable in bash command. See "?"
I thought we could almost run any bash statement with ! or host in front of line
#!/bin/bash
sqlplus scott/tiger#orcl << EOF
! export v10="Hi" Doesn't work, why?
! echo $v10 Doesn't work, why?
! echo "Done" Works perfectly and also other bash commands
select * from dept; Works perfectly
exit
EOF
Thank you
What #jordanm says "probably" is exactly what is happening. When you specify a host command from within sqlplus, a separate shell process is spawned, the command executed by that process, then that process is terminated and control returns to sqlplus. Any environment variables that are set in that child shell process are good only within it, so when it terminates, they are gone.
As for your specific lines that "work" and "don't work" .. "export v10="Hi" does work but there is no stdout display of the 'export' command, and as explained, that variable v10 ceases to exist once the child process completes and control returns to sqlplus. The "echo $v10" also works, but since that is a new shell process, it has no value for $v10, so there is nothing to echo.
What are you trying to accomplish by setting enviornment variables from within sqlplus?
found it, all I had to do was
<< EOF
whenever sqlerror exit failure rollback
whenever oserror exit failure rollback
#scriptname.sql
EXIT
EOF
I want to use the pidof by a process given by name in tcl. I have used [exec pidof $proc_name ], but it always returns an error: child process exited abnormally.
I read somewhere exec always treat non-zero return as error as pidof return the process id number. Does anyone know if there is a workaround? Thanks in advance!
I want to use pidof is that i want to see if that process is running if not i will restart the process.
The problem is that pidof does strange things with exit codes:
Exit Status
At least one program was found with the requested name.
No program was found with the requested name.
This interacts badly with exec which treats a non-zero exit code as indicating that it should tell the rest of Tcl that there was an error.
The simplest way of dealing with this is a little extra shell script wrapper. Let's hide it inside a procedure for convenience:
proc pidof {name} {
exec /bin/bash -c "pidof '$name'; exit \$(( \$? - 1 ))"
}
All that does is subtract 1 from the exit code before it hits back into Tcl.
(You could also fix this using the techniques described in the exec manual but I think it's simpler to fix on the bash side this time.)
I ran into this and ended up causing some issues with the old linux environment I run in (no bash and exit code handling was a bit different with busybox).
My solution that should work anywhere would be similar to what a few suggested:
proc pidof {name} {
catch {exec -ignorestderr -- pidof $name} pid
if {[string is entier -strict $pid]} {
return $pid
}
}
I am running below : sqlplus ABC_TT/asfddd#\"SADSS.it.uk.hibm.sdkm:1521/UGJG.UK.HIBM.SDKM\"
afte that I am executing one stored procedure exec HOLD.TRWER
I want to capture return code of the above stored procedure in unix file as I am running the above commands in unix. Please suggest.
I guess you are looking for spool
SQL> spool output.txt
SQL> select 1 from dual;
1
----------
1
SQL> spool off
Now after you exit. the query/stroed procedure output will be stored in a file called output.txt
If by return code you mean output then:
command > file
If by return code you mean exit status then:
command
echo "$?" > file
If you mean something else, let us know.
You can store command return value in variable
value=`command`
And then checking it's value
echo "$value"
For your case to execute oracle commands within shell script,
value=`sqlplus ABC_TT/asfddd#\"SADSS.it.uk.hibm.sdkm:1521/UGJG.UK.HIBM.SDKM\" \
exec HOLD.TRWER`
I'm not sure about the sql query, but you can get the returned results by using
value=`oraclecommand`.
To print the returned results of oracle command,
echo "$value"
To check whether oracle command or any other command executed successfully, just
check with $? value after executing command. Return value is 0 for success and non-zero for failure.
if [ $?=0 ]
then
echo "Success"
else
echo "Failure"
fi
I'm running DOS 6.0.6002 on a windows server enterprise system, SP2.
SQL Server 2008 R2 (10.50.4000)
I have a main control program in DOS.
I'm invoking an sql program through sqlcmd.
A simplified version looks like this:
set sqlsvr=myServer
set logfile=logfile.txt
sqlcmd -S %sqlsvr% -d myDB -i import_some_stuff.sql > "%logfile%" 2>&1
echo error level = %ERRORLEVEL%
I need this program to be pretty robust. It has to run every day against a lot of files and tables. If it fails, I need to catch it and notify sysadmin. For now, just catch it.
So to test this, I've tried the following tests:
1) Renaming the file to one that does not exist.
Result: it returns and errorlevel of 1 (that is it caught the error!) bravo!
2) typing in some syntactical rubbish at the front of the sql program.
Result: it prints the error message in the log file, BUT it DOES NOT return an error (so the return value in %ERRORLEVEL% is zero. This seems incredible to me. What am I missing?
Try the -b option to sqlcmd:
-b
Specifies that sqlcmd exits and returns a DOS ERRORLEVEL value when an
error occurs.
The value that is returned to the DOS ERRORLEVEL
variable is 1 when the SQL Server error message has a severity level
greater than 10; otherwise, the value returned is 0. If the -V option
has been set in addition to -b, sqlcmd will not report an error if the
severity level is lower than the values set using -V. Command prompt
batch files can test the value of ERRORLEVEL and handle the error
appropriately. sqlcmd does not report errors for severity level 10
(informational messages).
If the sqlcmd script contains an incorrect comment, syntax error,
or is missing a scripting variable, ERRORLEVEL returned is 1.
Here is the documentation