Update oracle table with start and end times from shell script - shell

There are three materialized views being refreshed in a single shell script(.ksh) and I am trying to insert the start, end timestamps for each MV in a oracle table(created for audit purpose). I tried creating a .sql file with insert statement that is being called at end of each refresh but unable to get the intended result. This is the first time I am working on shell script, can anyone please help me?
Thanks and Regards
Kiran.
CODE:
typeset -Z6 i
i=0
echo $PROP_FILE
VIEWS=$(echo $viewset| tr "," " ")
for VIEW in $VIEWS
do
echo "Generating $XML_FILE"
echo " "
echo "Start Refresh view: ${VIEW} at : $(date)"
if [ $DB_READ_FLAG -eq 0 ]
then
echo "calling launch_sqlplus.ksh "
#YRV
#Adding below line fix the defect 7494
#$BIN/launch_sqlplus.ksh $SQL/exports_refresh_view.sql $VIEW \
#$BIN/launch_sqlplus.ksh $SQL/exports_refresh_view.sql $VIEW || exit_with_error
else
echo "calling launch_sqlplus_read."
#YRV
#Adding below line fix the defect 7494
#$BIN/launch_sqlplus_read.ksh $SQL/exports_refresh_view.sql $VIEW \
# $BIN/launch_sqlplus_read.ksh $SQL/exports_refresh_view.sql $VIEW || exit_with_error
fi
echo "End Refresh view: ${VIEW} at : $(date)\n"
LOG FILE:
Start Refresh view: mv_lt_port_config at : Wed Aug 27 20:09:34 METDST
2014 calling launch_sqlplus_read.
Loading /isii/isi/bin/isi_profile_read isii
Launch SQL-script with paramaters :
/isii/isi/sql/exports_refresh_view.sql mv_lt_port_config
Session altered.
Session altered.
Session altered.
Session altered.
old 1: ALTER SESSION SET tracefile_identifier=mv_refresh_&1 new 1:
ALTER SESSION SET tracefile_identifier=mv_refresh_mv_lt_port_config
Session altered.
Session altered.
Session altered.
old 2: xml_report.refresh_mview('&1'); new 2:
xml_report.refresh_mview('mv_lt_port_config');
PL/SQL procedure successfully completed.
End Refresh view: mv_lt_port_config at : Wed Aug 27 20:12:17 METDST
2014

This answer may be partial, because of incomplete code in the question, however values can be inserted into a DB table from a ksh script as follows:
Assuming a DB Table is created -
CREATE TABLE VIEW_REFRESH_LOG
(OPERATION VARCHAR2(60),
START_DATE DATE,
END_DATE DATE);
Then the following sql file can be created -
REM ----------- insertRecord.sql -------------------------------
DEFINE DATEFORMAT = 'DD-MM-YYYY HH24:MI:SS'
DEFINE OPERATION = &1
DEFINE STARTING = '&2 &3'
DEFINE ENDING = '&4 &5'
INSERT INTO refresh_log
( operation,
start_time,
end_time)
VALUES
('&OPERATION',
to_date('&STARTING','&DATEFORMAT'),
to_date('&ENDING','&DATEFORMAT'));
COMMIT;
EXIT SUCCESS;
then, in the shell script -
...
CREDENTIALS="oracle_user/oracle_pass"
echo "Start Refresh view: ${VIEW} at : $(date)"
if [ $DB_READ_FLAG -eq 0 ]
then
echo "calling launch_sqlplus.ksh "
#YRV
#Adding below line fix the defect 7494
STARTDATE=$(date '+%d-%m-%Y')
STARTTIME=$(date '+%H:%M:%S')
#$BIN/launch_sqlplus.ksh $SQL/exports_refresh_view.sql $VIEW \
$BIN/launch_sqlplus.ksh $SQL/exports_refresh_view.sql $VIEW || exit_with_error
ENDDATE=$(date '+%d-%m-%Y')
ENDTIME=$(date '+%H:%M:%S')
PARAMETERS="'launch_sqlplus ${VIEW}' '${STARTDATE}' '${STARTTIME}' '${ENDDATE}' '${ENDTIME}'"
sqlplus -S $CREDENTIALS #insertRecord.sql "$PARAMETERS"
else
echo "calling launch_sqlplus_read."
#YRV
#Adding below line fix the defect 7494
STARTDATE=$(date '+%d-%m-%Y')
STARTTIME=$(date '+%H:%M:%S')
#$BIN/launch_sqlplus_read.ksh $SQL/exports_refresh_view.sql $VIEW \
$BIN/launch_sqlplus_read.ksh $SQL/exports_refresh_view.sql $VIEW || exit_with_error
ENDDATE=$(date '+%d-%m-%Y')
ENDTIME=$(date '+%H:%M:%S')
PARAMETERS="'launch_sqlplus_read ${VIEW}' '${STARTDATE}' '${STARTTIME}' '${ENDDATE}' '${ENDTIME}'"
sqlplus -S $CREDENTIALS #insertRecord.sql "$PARAMETERS"
fi
echo "End Refresh view: ${VIEW} at : $(date)\n"
That would derive the start and end time of the operation you're performing, and pass it as parameters to SQL*Plus, which takes those parameters and inserts them as bind variables into the sql script.
You need to be wary of the quotes when passing strings as parameters to SQL*Plus. Also, you'd want to modify your DATEFORMAT to whatever your value is for NLS_DATE_FORMAT.
Hopefully that addresses your question. If not, please clarify further.

Related

Script with multiline string and for loop

Writing a quick script for a temporary/repetitive task. Wrote a basic solution that works:
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
This works but forces a password check for every member of argument array (not ideal).
Tried to update it to this:
if {$# -le 1}; then
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
else
things = ""
for thing in "$#";
do
things += "$thing"
if {$thing == $#[$# - 1]}; then
things += "\n"
continue
else
things += ",\n"
done
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id IN
(
$things
)
END
TLDR: If there is more than one argument: do a for loop to fill a WHERE .. IN () statement. I realize this doesn't even need to be a multiline string and maybe that is my issue but the error I'm getting is (apparently) unrealted .
The error I get is:
line 24: syntax error near unexpected token' done'
line 24: ' done'
Neither I, nor my supervisor have much experience with shell scripts but I cannot see any syntax error with the 2nd for loop. Its exactly the same as the first which executes fine.
Any help is greatly appreciated, I may just have to go to the basic version or write this as a Perl script instead. Thanks!
Thanks everyone for all the advice. This was an edit that worked:
#!/bin/sh
if [ $# -le 1 ]; then
for thing in "$#";
do
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id = $thing
END
done
else
things=""
i=1
for thing in "$#";
do
things+="$thing"
if [ $i -eq $# ]; then
things+=""
else
things+=", "
fi
((i+=1))
done
/usr/mysql/bin/mysql -u xyz -p pdq <<END;
UPDATE table
SET table_atr = 'NW'
WHERE record_id IN ($things)
END
fi
There were indeed many syntax errors and changing the WHERE .. IN () string construction to a single line made this a lot easier. Luckily I didn't have to worry about inserting single quotes, mysql took the query without them.
I came out of this with a much higher respect for bash scripting. It is a serious language that requires its own study and I will approach it with much more attention to detail in the future.
Thanks again.

Iterating through PL/SQL result in shell script

I am new to the shell scripting hence need help. I am trying to execute sql query against Oracle DB. Once sql query result is received, I need to iterate through the result (as it will return multiple rows and columns.).
Goal here is to invoke a REST api using curl for each record retrieved in db result. Input to REST api will be ROOT_PROC_ID column value.
Below is the shell script I have developed so far and sample output of the sql query.
#!/bin/bash
#Update below properties as per enviornment
export ENV=DEV;
export SERVERHOST=localhost
export SERVERPORT=9000
export SERVERUSER=admin
export SERVERPASSWORD=admin123
export DBHOST=localhost
export DBPORT=1537
export DBSID=ORCL
export DBUSER=SCOTT
export DBPASS=TIGER
export LOGDIR=/usr/app/$USER/data/logs/
#-------------------------------------------------------------------------
#----------- DO NOT EDIT AFTER THIS LINE ---------------------------------
#-------------------------------------------------------------------------
#create directory structure if not exists for storing log files
mkdir -p $LOGDIR/process_cancellation
mkdir -p $LOGDIR/process_cancellation/old
mkdir -p $LOGDIR/process_cancellation/halted
export old_proc_cancellation_logfile=$LOGDIR/process_cancellation/old/log_$(date "+%Y%m%d%H%M%S").log;
export halted_proc_cancellation_logfile=$LOGDIR/process_cancellation/halted/log_$(date "+%Y%m%d%H%M%S").log;
#execute sql query to fetch halted process data from database
echo
echo "Enviornment : $ENV"
echo
echo "Connecting to - $DBUSER/$DBPASS#$DBHOST:$DBPORT/$DBSID"
echo
echo "Retrieving halted process data logged before : $(date -d "15 days ago" +%d/%m/%Y) 20:00:00"
echo
sqlplus -s $DBUSER/$DBPASS#$DBHOST:$DBPORT/$DBSID << FIN_SQL > $halted_proc_cancellation_logfile
set head off
set line 1024
set pages 9999
SET SERVEROUTPUT ON;
SELECT ROOT_PROC_ID, PROC_ID, PROC_NAME, START_DATE, STATUS, ORDER_REF
FROM USER.PROC_STATUS
WHERE START_DATE<(SYSDATE - 15) AND (STATUS='proc_halted' OR STATUS='proc_failed')
ORDER BY START_DATE DESC;
SET SERVEROUTPUT OFF;
FIN_SQL
echo "Please check log file for more details : $(readlink -f $halted_proc_cancellation_logfile)"
exit
Sample SQL query output:
ROOT_PROC_ID PROC_ID PROC_NAME START_DATE STATUS ORDER_REF
pvm:0a123akpd pvm:0a123akkh FunctionalErrorProcess 28-NOV-19 01.24.35.115000000 PM pi_halted 2642277
pvm:0a122utrn pvm:0a122uun0 TechnicalErrorProcess 22-NOV-19 02.28.17.217000000 PM pi_halted 2642278
pvm:0a122utl2 pvm:0a122uu1t TechnicalErrorProcess 22-NOV-19 02.27.54.024000000 PM pi_halted 2642279
pvm:0a122utln pvm:0a122uu22 TechnicalErrorProcess 22-NOV-19 02.27.50.287000000 PM pi_halted 2642280
Assuming your sql query output is in output.txt:
awk 'NR!=1' output.txt | while read rootprocid undef
do
callApi $rootprocid
done
NR!=1 is to skip the 1st line which contains the header.
read rootprocid undef reading only the 1st column in rootprocid, rest goes to variable undef since it is not of interest.
callApi $rootprocid callAPI will be replaced with your actual api call.

Updating records on a oracle database using shell script

I need to develop a shell script that updates some records on a oracle database, this programs read an input .txt file and then updates the record when some conditions are met, but for some reason this records were not updated, it seems that there's a problem with a variable that the plsql reads in order to update the records.
This is the shell script code
## #!/bin/sh
. /usr/local/bin/oracle.profile.prod
. /usr/local/bin/bscs.profile.prod
hostname=`uname -n`
basedato=BSCS1REP
if [[ $basedato = "BSCS2PROD" && $hostname = "comp35" ]];then
export Y/Shell
export Y/Sql
export Y/Log
export Y/Cfg
. Y.MM.txt
elif [ $basedato = "BSCS1REP" and $hostname = "comp44" ]; then
export X/Shell
export X/Sql
export X/Log
export X/Cfg
. X/.MM.txt
else
echo "ERROR, Servidor no valido para la ejecucion de este programa"
echo "Base de Datos = "$basedato
echo "Maquina = "$hostname
exit 1
fi
FECHA=$(date "+%Y%m%d_%H_%M_%S")
cat $RUTA_CFG/MSISDN.txt | while read elemento
do
set $elemento
elemento=$1
echo "El registro es $elemento "insertado""
sqlplus -S $USER/$PASS#$basedato #$RUTA_PLS/Num_Act.sql $elemento > $RUTA_LOG/test.txt
done
rm -f $RUTA_CFG/Act_num.ctl
echo "DONE"
As you can see this script reads an input data, is the following:
123456789
Just this simple string.
Now this is the invoked Pl/sql
ALTER SESSION SET OPTIMIZER_GOAL = CHOOSE;
ALTER SESSION SET NLS_LANGUAGE = AMERICAN;
ALTER SESSION SET NLS_TERRITORY = AMERICA;
SET serveroutput ON SIZE 1000000
SET term ON
WHENEVER SQLERROR CONTINUE
DECLARE
elemento constant varchar2(30) := '$1';
BEGIN
update directory_number dn
set dn.dn_status = 'a'
where dn.dn_num = ('$1')
and dn.dn_status in ('d','t','Z','f','r');
DBMS_OUTPUT.PUT_LINE (elemento);
END;
/
EXIT;
I added a log file to see what's going on, and it returned the following:
Session altered.
Session altered.
Session altered.
$1
PL/SQL procedure successfully completed.
The variable stands $1, and it should be the input data number.
Could be a sintax error ?, a variable declaration ?
When I put aside the variables and put directly the valor of the desire number in the plsql it updated the record with no problems.
Any help with be appreciated, thank so much for your time !
In your PL/SQL code try replacing $1 with &1.
See this link for an example and description.

Variable won't resolve inside PL-SQL statement

I am trying to pass a SQL command to the SQL*Plus command-line program (Oracle) in my KornShell (ksh) script, but my $MY_VAR variable seems to be failing to resolve. $MY_VAR is a string value.
sqlplus -s << EOF >> $LOG_FILE
$MY_SCHEMA
UPDATE my_table SET run_flag = 'I', start_time = to_char(sysdate, 'DD-Mon-YYYY HH24:MI:SS') WHERE (process_id = '$MY_VAR' AND run_flag != 'F');
COMMIT;
EOF
I can successfully echo out the $MY_VAR variable, and so I can see that the variable is populated, but it does not seem to be resolving when inserting the variable into the SQL command which I am providing as an argument to the SQL*Plus program. The log file for the script simply outputs:
0 rows updated. Commit complete.
The SQL seems to be valid as we can successfully execute the command in SQL Developer (albeit with a hardcoded value for $MY_VAR).
Any ideas on what I am missing here?
Thank you
Try this:
sql="$MY_SCHEMA
UPDATE my_table SET run_flag = 'I', start_time = to_char(sysdate, 'DD-Mon-YYYY HH24:MI:SS') WHERE (process_id = '$MY_VAR' AND run_flag != 'F');
COMMIT;"
print "$sql"
sqlplus -s <<<"$sql" >> $LOG_FILE
Does the sql look correct? If it does and zero rows are updated, your where clause must be selecting zero rows.
Your version of ksh may not have the <<< here-string syntax. In that case:
print "$sql" | sqlplus -s >> $LOG_FILE

Check if value within column exists, if not create the column

I need to check if one of the columns in my db contains specific value. If it doesn't I want to create that row with folowing values:
#!/bin/bash
#
MODEL=$1
if true (SELECT * FROM table.STATISTICS
WHERE MODEL = '$MODEL' )
do this (INSERT INTO table.STATISTICS('$MODEL',0,SYSDATE,0,SYSDATE,0); )
You could use a merge for this, run through SQL*Plus as a 'heredoc', so you don't have to do a separate count operation; the merge will do that for you effectively:
#!/bin/bash
MODEL=$1
sqlplus -s /nolog <<!EOF
connect user/pass
merge into statistics s
using (select '${MODEL}' as model, 0 as num1, sysdate as date1,
0 as num2, sysdate as date2 from dual) t
on (s.model = t.model)
when not matched then
insert (s.model, s.num1, s.date1, s.num2, s.date2)
values (t.model, t.num1, t.date1, t.num2, t.date2);
!EOF
But using your real column names, obviously. It's better to list them explicitly even for a plain insert.
get_count () {
sqlplus -s username/pass <<!
set heading off
set feedback off
set pages 0
select count(model) from statistics
where model='$MODEL';
!
}
count=$(get_count $1)
if [ "${count:-0}" -eq 0 ]; then
echo "its zero"
sqlplus -S username/pass << EOF
whenever sqlerror exit 1;
set echo on
set verify off
INSERT INTO table.STATISTICS VALUES('$MODEL',0,SYSDATE,0,SYSDATE,0);
exit;
EOF
fi

Resources