How to call oracle function from a Korn Shell Script? - oracle

I have a user defined oracle function that returns a number that can be greater than 255. I call that function from a shell script using sql plus, it returns the value, for eg 296, but the scripts accepts it as 40, which is because the script can only accept return codes from 0-255.
This is how i am currently receiving the value
echo ${PASSWORD} | sqlplus ${USERNAME}#${SID} #$SQL getnumber.sql $PARAM> ${LOG}
number=$?
getnumber.sql has
set serveroutput on size 100
VARIABLE rc NUMBER;
call function_get_number('&2') into :rc;
print rc;
exit :rc;
How can i preserve the return value? Should i write it to a file? if so how/where

Script getnumber.sh:
cat << EOF | sqlplus /S /nolog >${LOG}
conn ${USERNAME}/${PASSWORD}#${SID}
set serveroutput on size 100
VARIABLE rc NUMBER;
exec :rc := function_get_number('$PARAM');
SELECT 'RETVAL:' || :rc || ':' theval FROM dual;
EOF
RC=$( grep '^RETVAL:' ${LOG} | cutr -d":" -f2 )
echo $RC

Related

How to capture the output of a PL SQL function in a powershell variable?

I am able to connecting to remote oracle database using powershell and sqlplus. Also I am able to capture the output of the command/query executed in the database into a powershell variable.
PFB example.
$username ="hr"
$password ="hr"
$tnsalias ="orcl"
$outputfilepath="C:\Users\Desktop"
$sqlquery=#"
set serveroutput off
set feedback off
set heading off
set echo off
select sysdate from dual;
"#
Running the above query in oracle database as below
$xval=$sqlquery | sqlplus -silent $username/$password#$tnsalias
echo $xval
The output will be
23-APR-18
The problem is when I am running a PL SQL function as below.
$sqlquery=#"
set serveroutput off
set feedback off
set heading off
set echo off
declare
x varchar2:=null;
exec x:=MYTEST_FUN('a','b');
"#
There is no value captured in the $xval variable and also the function is not running.
How to execute the function such that the return value of the function is captured in a powershell variable.
One way is to make it set serveroutput on and use DBMS_OUTPUT.PUT_LINE() within BEGIN..END
Another option is to use the sqlplus' PRINT command.
set serveroutput off
set feedback off
set heading off
set echo off
variable x VARCHAR2 --declare bind variable x
exec :x := MYTEST_FUN('a','b'); --a colon before x needed.
PRINT x;
Worked for me:
$sqlQuery = #"
set serveroutput off
set feedback off
set heading off
set echo off
variable x NUMBER;
select count(*) into :x from TABLE;
PRINT x;
exit
"#
($sqlQuery | sqlplus -S user/pass | Write-Output | Out-String).Trim()
Late entry, most concisely:
$dateVar = ("set heading off
select sysdate from dual;" | sqlplus -s $yourConnectionString | Out-String).Trim()

Passing an out clob procedure parameter as it is to a shell variable

I have a procedure that takes a clob as an out parameter.
I want to pass the clob content to the shell variable so that I can print it in a file, as it is in one line, but I got a different result : some blanks are deleted, and the result is printed in many lines!
This is the shell code :
#!/bin/bash
date_fich_ent=`date '+%Y%m%d'`;
heure_fich_ent=`date '+%H%M'`;
FILE_NAME="RIA_BMCE_TRX_${date_fich_ent}${heure_fich_ent}.TXT";
function_output=`sqlplus -s <<END
$1/$2#$3
set feedback off
set heading off
set pagesize 0
set serveroutput on 100000
DECLARE
my_clob clob := null;
BEGIN
proc_test('it',my_clob);
dbms_output.put_line(my_clob);
END;
/
exit;
END`
echo "$function_output" > $FILE_NAME
Thanks.

BASH commands inbetween SQLPlus code or how to count the time used to run different SQLplus commands?

For performance testing purposes - I need to count duration of SQLPlus query. Its not so simple as it seems to be.
I have the code here:
VARIABLE RC REFCURSOR;
EXEC :RC := $aktuellesBericht;
SPOOL ${BERICHT}_${configArray[0]}.DATA
PRINT RC;
SPOOL OFF
It's just a part of the whole command. The whole command looks like this:
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
CONNECT USER/PASSWORD#DATABASE
#A ton of unimportant SET and CLEAR commands goes here#
VARIABLE RC REFCURSOR;
EXEC :RC := $aktuellesBericht;
SPOOL ${BERICHT}_${configArray[0]}.DATA
PRINT RC;
SPOOL OFF
QUIT
EOF
I need to count time of EXEC :RC := $aktuellesBericht; and PRINT RC; separately. Is this even possibe? Can I count it somehow? Let me use some pseudocode showing what I want to do:
execstart = date +%s%N
EXEC :RC := $aktuellesBericht;
execend = date +%s%N
SPOOL ${BERICHT}_${configArray[0]}.DATA
printstart = date +%s%N
PRINT RC;
printend = date +%s%N
SPOOL OFF
exectime=$(( execend - execstart ))
printtime=$(( printend - printstart ))
echo $exectime;
echo $printtime;
bash has a builtin time command which executes a command then print various times :
If the time reserved word precedes a pipeline, the elapsed as well as
user and system time consumed by its execution are reported when the
pipeline terminates. The TIMEFORMAT variable may be set to a format string that specifies how the timing
information should be displayed;
# only the real time
TIMEFORMAT="This was done in : %R seconds"
time EXEC :RC := $aktuellesBericht;

SQLPLUS output to shell script not returning value

I'm trying to return a sqlplus output to a shell script. This may sound simple enough but I've searched online for some time and cannot get my script to work.
Here is my pl/sql script:
SET SERVEROUTPUT ON
DECLARE
X_RETURN_MSG VARCHAR2(32767);
X_RETURN_CODE NUMBER;
BEGIN
X_RETURN_MSG := NULL;
X_RETURN_CODE := 5;
COMMIT;
END;
EXIT X_RETURN_CODE;
Here is my shell script:
sqlplus -s user/pwd <<EOF
#../sql/tester.sql
EOF
RETVAL=$?
echo $RETVAL
$RETVAL always returns 0 even when I have X_RETURN_CODE := 5
X_RETURN_CODE has no meaning outside of the scope of the PL/SQL block where it is declared. You need to use a SQLPlus bind variable.
SQL> VARIABLE return_code NUMBER
SQL> BEGIN
2 :return_code := 5;
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> EXIT :return_code
Disconnected from Oracle Database 10g Release 10.2.0.4.0 - Production
> echo $?
5
My guess is END marks the end of the block and X_RETURN_CODE goes out of scope so it defaults to 0. Or maybe you should look into using the RETURN statement instead of EXIT.
$ sqlplus -s <<!
> / as sysdba
> #tester
> !
PL/SQL procedure successfully completed.
$ echo $?
5
$ cat tester.sql
SET SERVEROUTPUT ON
var X_RETURN_CODE number
DECLARE
X_RETURN_MSG VARCHAR2(32767);
BEGIN
X_RETURN_MSG := NULL;
:X_RETURN_CODE := 5;
COMMIT;
END;
/
EXIT :X_RETURN_CODE;

How to store multiple output columns returned by stored proc in shell using sqlplus

I have o read values returned by sql stored proc to variables in shell script. I was able to achieve this with single variable but not for two variables.
Oracle stored proc
PROCEDURE get_values (ip_var IN NUMBER,
op_var1 OUT VARCHAR2,
op_var2 OUT VARCHAR2)
IS
BEGIN
SELECT col1, col2
INTO op_var1, op_var2
FROM emp
WHERE emp_id = ip_var;
END;
Calling this proc in unix bash as
sql_status=`sqlplus -silent /nolog << END
whenever sqlerror exit sql.sqlcode
whenever oserror exit -2
set pagesize 0 feedback off verify off heading off echo off scan off serveroutput on
connect $DATABASE
declare
var1 VARCHAR2(20);
var2 VARCHAR2(20);
begin
get_values($input_val, var1, var2);
end;
/
exit;
END`
I need to assign var1 and var2 further in my program. So how can I achieve this?
I know not how to do this interface between PL/SQL (Oracle Server side language) and Unix. You may want to have a jdbc connector for more advanced use.
A solution for your problem is to build an output string directly from the query (or you could use a procedure, and output the result with dbms_output), and process the string in your shell.
Here is how (without procedure):
COL_SEP="%"
RETURN_STRING=`sqlplus -silent /nolog << END
whenever sqlerror exit sql.sqlcode
whenever oserror exit -2
set pagesize 0 feedback off verify off heading off echo off scan off serveroutput on
connect $DATABASE
SELECT col1 ||'${COL_SEP}'|| col2
FROM emp
WHERE emp_id = ip_var;
exit;
END`
echo "RETURN CODE IS: $? "
echo "RETURN STRING : ${RETURN_STRING} "
v1=`echo ${RETURN_STRING} | cut -d${COL_SEP} -f1 `
v2=`echo ${RETURN_STRING} | cut -d${COL_SEP} -f2 `
echo "Variables set: V2:${v2} and V1:${v1}"
And you can do it with dbms_output.put_line in a pl/sql block:
declare
v varchar2(100) := '00';
begin
select 'a'||'${COL_SEP}'||'b' into v from dual;
dbms_output.put_line(v);
end;
/
Hope it helps

Resources