How to capture the result of stored procedure through shell script? - sql

I'm trying to execute stored procedure through shell script and try to get return from stored procedure but I didn't get any thing from the stored procedure on other hand same thing I do with sqlplus prompt and I'm able to get the result
sqlplus -silent xxx#xxx <<EOF
set serveroutput on
declare
DE_REC_COUNT number(10);
begin
DE_DUP_PROC ('T_MCL_30404_20150317_020','MCL','30404','FT',DE_REC_COUNT);
end;
EOF
Through sqlplus prompt
SQL> set serveroutput on
declare
DE_REC_COUNT number;
begin
DE_DUP_PROC ('T_MCL_30404_20150317_020','MCL','30404','FT',DE_REC_COUNT);
end;
0
PL/SQL procedure successfully completed.

The version of the anonymous block in the shell script will not be executed as shown, because you don't have a slash after the block to run it. If you run that you get no output at all. If you change it to have a slash:
sqlplus -silent xxx#xxx <<EOF
set serveroutput on
declare
DE_REC_COUNT number(10);
begin
DE_DUP_PROC ('T_MCL_30404_20150317_020','MCL','30404','FT',DE_REC_COUNT);
end;
/
EOF
then you'll see:
0
PL/SQL procedure successfully completed.
You've shown the interactive version in SQL*Plus without the slash too, but you must have had that to see the output you showed.
If you want the zero - which seems to be coming from a dbms_output call in your procedure, rather than directly from your anonymous block - n a shell variable you can refer to later, you can assign the output of the heredoc to a variable:
MY_VAR=`sqlplus -silent xxx#xxx <<EOF
set serveroutput on
set feedback off
declare
DE_REC_COUNT number(10);
begin
DE_DUP_PROC ('T_MCL_30404_20150317_020','MCL','30404','FT',DE_REC_COUNT);
end;
/
EOF`
printf "Got back MY_VAR as %s\n" ${MY_VAR}
Note that I've added set feedback off so you don't see the PL/SQL procedure successfully completed line. Now when you run that you'll see:
Got back MY_VAR as 0
and you can do whatever you need to with ${MY_VAR}. It depends what you mean by 'capture' though.

Here's an example of how it can be done by surrounding the code with the evaluation operators (` back quotes):
#!/bin/sh
results=`sqlplus -s xxx#xxx <<EOF
set serveroutput on feedback off
declare
DE_REC_COUNT number(10);
begin
DE_DUP_PROC ('T_MCL_30404_20150317_020','MCL','30404','FT',DE_REC_COUNT);
end;
/
EOF`
echo $results

Lets say for instance I have a below procedure which calculates the sum of two numbers and prints the total using dbms_output.put_line() method
CREATE OR REPLACE
PROCEDURE SUM
(
a IN NUMBER,
b IN NUMBER)
AS
total NUMBER;
BEGIN
total:= a + b;
dbms_output.put_line(total);
END;
Then in order to call this in our shell script we need to call this procedure in an anonymous block and store in a variable, later using echo we can execute the command.
plsqlcode=`sqlplus -silent hr/sandeep#orcl <<EOF
set serveroutput on
begin
sum(10,20);
end;
/
EOF`
echo $plsqlcode
Ideally this is not a recommended approach you should keep your shell and pl/sql code in separate files.

Related

How to reproduce ORA-01940: cannot drop a user that is currently connected through Jenkins pipeline?

Through Jenkins pipeline, if I get error ORA-01940: cannot drop a user that is currently connected, I want to perform some action.
FOr testing I should get that message. If I create user and log in with it to sql developer and try to drop it through pipeline it results into above error -
sh '''
sqlplus -s /nolog <<-EOF
connect system/system#orcl
DROP USER TEST_USER;
exit
EOF
'''
Is there any way I can connect using that user and drop it through pipeline so results into above error?
If you are running that part through a PIPELINE in Jenkins using shell script, there are some options:
Get a specific Return Code of the Operation
In this case, you might do the following
sh '''
sqlplus -s /nolog <<-EOF
connect system/system#orcl
whenever sqlerror exit 99
DROP USER TEST_USER;
exit
EOF
'''
This operation will return 99 in case you got the error. You must evaluate the the return of the operation using $?
Example
Session 1 ( as system )
SQL> create user test identified by Oracle_1 ;
User created.
SQL> grant connect to test ;
Grant succeeded.
I connect with the user test, and then with my system user I will try to drop it
SQL> whenever sqlerror exit 99
SQL> drop user test ;
drop user test
*
ERROR at line 1:
ORA-01940: cannot drop a user that is currently connected
Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64 bit Production
[ftpcpl#scglvdoracp0040 ~]$ echo $?
99
Using PLSQL Block to return code or message
However, if you want something different than the option before, like having the code displayed automatically without evaluation, then you can get the message display by the output using an anonymous PL/SQL block.
In your case, I would use something like this:
sh '''
sqlplus -s /nolog <<-EOF
connect system/system#orcl
set serveroutput on feedback off
declare
user_is_conn exception;
verror varchar2(100);
pragma exception_init ( user_is_conn , -1940 );
begin
execute immediate q'[ DROP USER TEST ]';
exception
when user_is_conn then
verror := sqlerrm ; -- the whole error message
-- verror := sqlcode ; -- only the code 1940
dbms_output.put_line(verror); -- message
when others then
raise;
end;
/
exit
EOF
'''
I commented verror := sqlcode in the section before to show the whole message. An example of this running in Linux would be:
$ $ORACLE_HOME/bin/sqlplus -S "/ as sysdba" << eof
set serveroutput on feedback off
declare
user_is_conn exception;
verror varchar2(100);
pragma exception_init ( user_is_conn , -1940 );
begin
execute immediate 'DROP USER TEST' ;
exception
when user_is_conn then
verror := sqlerrm ;
dbms_output.put_line(verror);
when others then
raise;
end;
/
eof
ORA-01940: cannot drop a user that is currently connected
Be aware that this PL/SQL block is ended OK. I mean, from OS perspective the operation return code is 0. If you want that as a error, you need to raise the error, but in that case the message would be different.

Oracle - How to pass a parameter from batch file to SQL file which contains a PL/SQL procedure

I written a command in batch file which calls a .sql file which contains a pl/sql procedure. But I need to set the a parameter in PL/SQL procedure which common throughout the procedure from the batch file.
The batch file is as below.
set parameterOne=%1
set parameterTwo=%2
sqlplus -s uid/pwd filepath/filename.sql %parameterOne %parameterTwo
And the PL/SQL procedure in .sql file is as follow.
DECLARE parameterOneValue INT;
parameterTwoValue INT;
BEGIN
parameterOneValue := $(parameterOne);
parameterTwoValue := $(parameterTwo);
//procedure block
END;
I need to set the parameterOne, parameterTwo attribute from batch file to parameterOneValue, parameterTwoValue in .sql files respectively. Could anyone provide solution to this?
Use SET DEFINE ON, and use & for variable substitution.
For example,
Your batch file:
set parameterOne=%1
set parameterTwo=%2
sqlplus -s uid/pwd filepath/filename.sql %parameterOne %parameterTwo
SQL*Plus substitution in PL/SQL block:
parameterOneValue := &1;
parameterTwoValue := &2;
& will substitute the actual value that you set in the batch file.

SQLPLUS script calling a function and executing the return String

I have an sqlplus script which needs to call a function. This function creates an SQL select dynamically and has already been compiled in the database.
My script needs to call this function, executes the SQL request it returns and then spool the data in a CSV file.
My SQLPLUS code is below:
SET HEAD OFF
SET TRIMOUT ON
SET TRIMSPOOL ON
SET LINESIZE 32000
SET PAGESIZE 0
SET TERMOUT OFF
SET ECHO OFF
SET COLSEP ,
spool /a/b/rvibap/c/&1..csv
EXECUTE IMMEDIATE build_select(&1)
spool off;
/
However, I am getting the below error in my CSV file:
BEGIN IMMEDIATE build_select(TYPE); END;
*
ERROR at line 1:
ORA-06550: line 1, column 17:
PLS-00103: Encountered the symbol "BUILD_SELECT" when expecting one of the following:
:= . ( # % ;
The symbol ":=" was substituted for "BUILD_SELECT" to continue.
I am calling my SQL script in the following way :
#test.sql TYPE
I have also tested the build_select function and it functions correctly; return a query in String.
There are few issues with your code.
There is no BEGIN END block enclosing your EXECUTE IMMEDIATE
expression.
EXECUTE IMMEDIATE does not display the results of an sql select statement.
You are calling your execute script as #test.sql TYPE which will be parsed as EXECUTE IMMEDIATE build_select(TYPE) i.e plain TYPE without quotes - which will throw an error. You can resolve this however by running it as
#test.sql "'TYPE'"
As I said you cannot directly execute and view results from a dynamic SQL select statement in 11g and below. So you can use the technique used in the other answer which I am not clear about if it generates the select SQL neatly.
If you are in 12c, you can use something like
open a_ref_cursor for build_select(&1);
dbms_sql.return_result(a_ref_cursor);
For 11g and below , here are some of the techniques explained.
How to output result of SELECT statement which is executed using native dynamic SQL?
A better solution if you are ok not to use your function would be
Generating SQL*Plus script using SQL*Plus
Wrong syntax... Maybe you could call the spool you just created?
Here is what could work:
SET HEAD OFF
SET TRIMOUT ON
SET TRIMSPOOL ON
SET LINESIZE 32000
SET PAGESIZE 0
SET TERMOUT OFF
SET ECHO OFF
SET COLSEP ''
spool /a/b/rvibap/c/&1..sql
prompt SET COLSEP ,
select build_select(&1) from dual;
spool off;
spool /a/b/rvibap/c/&1..csv
#/a/b/rvibap/c/&1
spool off;
Hope it helps.

Print DBMS_OUTPUT.PUT_LINE in a file with a bash script

I have a pl/SQL query that has a variable .
I want DBMS_OUTPUT.PUT_LINE to a file used on the machine (linux)
Does someone know how to do this?
You need to put some pieces together. Here is my inspiration: DBMS_OUTPUT.PUT_LINE not printing
a) put your plsql in an sql script, e.g. d.sql - the key here is set serveroutput:
set serveroutput on size 30000;
begin
DBMS_OUTPUT.PUT_LINE('my line');
end;
/
exit
b) Then write another script - ksh this time - containing:
sqlplus / #d.sql > output.txt
If you want to restrain what displays from sqlplus, then read appropriate documentation about set statement

Cant print result in CMD with PL/SQL

I am new to PL/SQL, I have ran a simple command of Hello world in my command prompt.
DECLARE
message varchar2(20):= 'Hello, World!';
BEGIN
dbms_output.put_line(message);
END;
/
But The hello world did not get displayed in CMD although I am getting the message PL/SQL procedure successfully completed message.
Please help out!
SET SERVEROUTPUT ON
will help you to print messages from buffer to your CMD...
so try,
SET SERVEROUTPUT ON
DECLARE
message varchar2(20):= 'Hello, World!';
BEGIN
dbms_output.put_line(message);
END;
/
use the below sqlplus command to display the output of dbms_output.put_line
set serveroutput on
before running the anonymous block
We can write pl/SQL in workspace and execute easy.
Example hello world
Set serveroutput on
Declare
message varchar 2(20):='Hello world';
Begin
dbms_output.put_line(message);
End;
/
Result will give
Hello world
Pl/SQL procedure successfully completed .