How to run sql script in an anonymous block? - sql

Is it possible to run an sql script in an anonymous block?
I would like to be able to conditionally run an sql script.
#!/bin/bash
.
.
.
`sqlplus -S /nolog > log3 << EOFSQL
connect ${userName}/${userPassword}#${urlDataBase};
set serveroutput on
set pagesize 0
set feedback off
set verify off
set heading off
set wrap off
set linesize 150
DECLARE
lv_error VARCHAR2(100):='';
BEGIN
SELECT TRIM(STATUS) INTO lv_error FROM tab1
WHERE ...
IF lv_error NOT LIKE 'ERROR%' THEN
START $(pwd)/script.sql;
/
END IF;
END;
/

In your case it is better to write a PL/SQL procedure and invoke it from the shell script. That way, it is easier to conditionally call the second sql function/procedure.
Or, if you want to keep the logic in shell script, spool the output of the first SQL and then read it and call the second sql script.
Something like this.
#!/bin/bash
.
.
.
sqlplus -S /nolog > log3 << EOFSQL
connect ${userName}/${userPassword}#${urlDataBase};
spool spool_out.txt
set linesize 150
DECLARE
lv_error VARCHAR2(100):='';
BEGIN
SELECT TRIM(STATUS) FROM tab1
WHERE ...
END;
/
EOFSQL
errorPresent=`cat spool_out.txt|grep "ERROR"`
if [ ! -z $errorPresent ]
the
#Call $(pwd)/script.sql;
fi

Related

SQLPLUS use optional parameters

Currently, I call an SQL File from a CMD file and transfer some parameters during the call. The code below works if I actually pass a value or press enter. However, my CMD/SQL will stop and wait for the parameter if there was none given. In such a case I would like to continue with default values instead.
CMD Code:
REM this works
sqlplus !dbuser! #!some_dir!\some_sql_file.sql test_text >> !log!
REM this STOPS and waits until user interaction happens
sqlplus !dbuser! #!some_dir!\some_sql_file.sql >> !log!
SQL Code:
set serveroutput on
SET LINESIZE 10000
declare
l_some_text varchar2(1000);
begin
select nvl('&&3','no_text_given') into l_some_text from dual;
dbms_output.enable;
dbms_lock.sleep(1);
dbms_output.put_line('SQL uses: ' || l_some_text );
end ;
Parameter can't be 3; there's only one, so it is supposed to be 1.
Here's option you might be interested in.
a.sql file:
set serveroutput on
set ver off
set termout off
column 1 new_value 1
select null as "1" from dual where 1 = 2;
set termout on
declare
l_some_text varchar2(1000);
begin
select nvl('&1', 'no_text_given') into l_some_text from dual;
dbms_output.put_line('SQL uses: ' || l_some_text );
end ;
/
exit;
Let's test it: with parameter passed to it:
c:\temp>sqlplus -s scott/tiger#pdb1 #a.sql littlefoot
SQL uses: littlefoot
PL/SQL procedure successfully completed.
Without parameter:
c:\temp>sqlplus -s scott/tiger#pdb1 #a.sql
SQL uses: no_text_given
PL/SQL procedure successfully completed.
c:\temp>
Adjust it, if you have to (e.g. redirect to file; remove various settings I used, ...) but - generally - that's what you asked for.
In cmd,
if not defined parameter set "parameter=defaultvalue"
sqlplus !dbuser! #!some_dir!\some_sql_file.sql !parameter! >> !log!
if parameter has not been set, uses default. You haven't shown us how you provide test_text to the cmd procedure; you would need to assign its value to parameter

variable value not assigned in cronjob

I have a code which when executed manually ( via this command i.e. ./script.sh ) assigns the query result to a variable but when it is executed automatically via crontab then the query result is not assigned to the variable.
Please find below the code:
diff=0;
diff=`sqlplus -s user/pswd#leadb2 << END
set pagesize 0 feedback off verify off heading off echo off;
SELECT (to_Date($timeRightNow,'YYYYMMDDHH24MISS') - to_date($timeoffile,'YYYYMMDDHH24MISS') ) * 24 * 60
difference_in_minutes
from dual;
END`
echo "Difference is $diff ">>/backup2/softdev/settlement/p.txt
It usually happens because your cron is not aware of your variables initialized in .profile. Even the path for sqlplus is not available, when you run this script via cron. So, to fix the issue, set the cron job in below format, and it will work fine.
00 * * * * . ~/.profile && /home/absolut_path_to_script.sh > /home/log_file_path.txt
i have done it as cron doesnot know the path of SQLPlus so it does not execute the query as soon as the path is given to cron the job responds perfectly
Here is the solution:
ORACLE_HOME=/oracle/app/oracle/product/11.2.0/db_1
export ORACLE_HOME
dateToday=date +%Y%m%d%H%M%S
diff=0;
timeRightNow='20170519180000'
timeoffile='20170519175500'
diff=$ORACLE_HOME/bin/sqlplus -s user/paswd#leadb2 << END
set pagesize 0 feedback off verify off heading off echo off;
SELECT (to_Date($timeRightNow,'YYYYMMDDHH24MISS') - to_date($timeoffile,'YYYYMMDDHH24MISS') ) * 24 * 60
difference_in_minutes
from dual;
END
echo "Difference is $diff ">>/backup2/softdev/settlement/p.txt

How to execute a query stored in a variable in SQL*Plus

Is there any way to pass a query to SQL*Plus through a variable?
I'm aware SQL*Plus has the capability to execute a file like:
sqlplus user/pass#db #filename
Within a kornshell script I'm trying to do:
query="select * from dual;"
sqlplus user/pass#db $query
There might have solution to do that BUT I can achieve the same goal using the following method.
[oracle#myserver Desktop]$ $ORACLE_HOME/bin/sqlplus -s jay/passsword#db <<!
select * from dual;
exit
!
D
-
X
Update, you can store the returned result in a variable as shown below.
query="select * from dual;"
var=$($ORACLE_HOME/bin/sqlplus -s jay/pass#db <<!
set pages 0
set head off
set feed off
$query
!
);

Pass shell variables to SQL statement

I want to pass shell variables to sql statement. Both shell script and SQL statement are present in the same script file.
I want the values of the variables retMonth, retLastDay and retPrvYear in the SQL statement.
Below is the code.
If I execute this, it prints - " partition_date between '01--' and '--' \ 0 0] 1 1] 12-DEC-14 1"
How can I have values of retMonth, retLastDay and retPrvYear in SQL statement?
echo $retMonth //This prints 07
echo $retLastDay //This prints 31
echo $retPrvYear //This prints 2015
count=$(sqlplus -s ${DBA_ORACLE_USER}/${DBA_ORACLE_PWORD}#${ORACLE_SID} <<END
#connect ${DBA_ORACLE_USER}/${DBA_ORACLE_PWORD}#${ORACLE_SID}
set serveroutput on
set linesize 1000
set heading off
set feedback off
define lastMonth=$retMonth
define lastYear=$retPrvYear
define lastDay=$retLastDay
SELECT count(1)
FROM MYTABLE
WHERE partition_date between '01-$lastMonth-$lastYear' and '$lastDay-$lastMonth-$lastYear'
);
END
)
Try using quoted shell variables directly without using define directives:
count=$(sqlplus -s "${DBA_ORACLE_USER}/${DBA_ORACLE_PWORD}#${ORACLE_SID}" <<END
set serveroutput on
set linesize 1000
set heading off
set feedback off
SELECT count(1)
FROM MYTABLE
WHERE partition_date between
"01-$retMonth-$retPrvYear" and "$retLastDay-$retMonth-$retPrvYear";
END
)

Store SQL query string into variable BASH

I have a select statement inside a bash script that returns the latest date in the DB. I run this query 4 times so I want to define it just once and assing the text to a variable.
#!/bin/bash
linux commands;
database_date=$(sqlplus -s/nolog $USER/$USER#BRMDPP <<END
set pagesize 0 feedback off verify off heading off echo off;
SELECT ...
exit;
END
)
commands that change the database date;
last_date=$(sqlplus -s/nolog $USER/$USER#BRMDPP <<END
set pagesize 0 feedback off verify off heading off echo off;
SELECT ...
exit;
END
)
commands that change the database date;
How can I store this big string $(sqlplus ... into one variable and use it again?
Thank you
One way would be to make use of a function:
foo() {
sqlplus -s/nolog $USER/$USER#BRMDPP <<END
set pagesize 0 feedback off verify off heading off echo off;
SELECT ...
exit;
END
}
and later invoke it by saying:
value=$(foo)
In order to get the value returned by the function, say echo "$value" (note that quoting variables is important).