Coding for GMT, sqlplus and related parameters

Unix gurus,

I'm brand new here so go easy on me.

I'm trying to automate the following script to be added to crontab which will automate the deployment of five sql scripts based on day of week. I've got three questions pertaining to the following:

  1. Our server date+time is running on GMT; how do I get perl to reflect day of week for GMT-4?
  2. I'm not sure if my sqlplus parameters are correct. The hardcoded values passed DO need to have a single quotation mark included when being passed. Is the way I've coded it, correct?
  3. Lastly, I'm calling sqlplus each time and passing user/passwd/sid for each script being called. Since each script should be running sequentially after each other, should I remove sqlplus for all subsequent calls? What is the best way to code this?
 
#!/bin/ksh
export USAGE="USAGE: `basename $0` -e <DBUSER> <DBPASSWD> <TNSNAME>"
if [ $# -lt 3 ]; then
  echo ${USAGE}
  exit 1;
fi
SCRIPTHOME=`home/users/pzx8pak`
TMS_USER=$1
TMS_PWD=$2
TMS_DATABASE=$3
LL="${TMS_USER}/${TMS_PWD}@${TMS_DATABASE}"
dow()  
{
 perl -e '
  use POSIX qw(strftime);
  $fmt = "%A";  # %a = abbreviated weekday %u = weekday number 
  $mday = substr("$ARGV[0]", 8, 2);
  $mon =  substr("$ARGV[0]", 5 ,2);
  $year = substr("$ARGV[0]", 0 ,4);
  $weekday =
    strftime($fmt, 0, 0, 0, $mday , $mon - 1, $year - 1900, -1, -1, -1);
  print "$weekday";
  ' "$1"
}
day = "$(dow `date "+%Y-%m-%d"` )"
 
if [[ ${day} = "Monday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2005'" "'01-JAN'" "'31-MAR'"
elif [[ ${day} = "Tuesday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2006'" "'01-JAN'" "'31-MAR'" 
elif [[ ${day} = "Wednesday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'" 
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2007'" "'01-JAN'" "'31-MAR'" 
elif [[ ${day} = "Thursday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"   
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2008'" "'01-JAN'" "'31-MAR'"  
 
elif [[ ${day} = "Friday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"   
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2009'" "'01-JAN'" "'31-MAR'"   
elif [[ ${day} = "Saturday" ]]; then
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"   
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"  
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql "'2010'" "'01-JAN'" "'31-MAR'"  
 
fi 
 
echo ""
echo ""
echo ""
echo "Deployments Complete"

Use TZ variable to set the time zone. You did not specify your OS, so a solaris example

TZ=US/Atlantic

Lose the perl, use

dow=`date +%A`

BE CAREFUL when you use relative paths (./) in cron.
crontab example

#monday
0 1 * * 1  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2005  > /path/to/logfile 2&>1 
#tuesday                                              
0 1 * * 2  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2006  > /path/to/logfile 2&>1 
                                                      
#wednesday                                            
0 1 * * 3  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2007  > /path/to/logfile 2&>1 
                                                      
#thursday                                             
0 1 * * 4  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2008  > /path/to/logfile 2&>1 
                                                      
#friday                                               
0 1 * * 5  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2009  > /path/to/logfile 2&>1 
                                                      
#saturday                                             
0 1 * * 6  . path/to/.profile && /path/to/myscript.sh -e user pwd db 2010  > /path/to/logfile 2&>1 

Then shorten your code sorta like this:

#!/bin/ksh

year()
{
   printf "'%s'" $1
}
export USAGE="USAGE: `basename $0` -e <DBUSER> <DBPASSWD> <TNSNAME>"
if [ $# -lt 3 ]; then
  echo ${USAGE}
  exit 1;
fi
SCRIPTHOME=`home/users/pzx8pak`
TMS_USER=$1
TMS_PWD=$2
TMS_DATABASE=$3
LL="${TMS_USER}/${TMS_PWD}@${TMS_DATABASE}"
 cd ${SCRIPTHOME}
 sqlplus -s ${LL} @./SCR_MTL_CST_TXN_COST_DETAILS_PRE_OUTAGE.sql "$(year $4)" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_MATERIAL_TRANSACTIONS_PRE_OUTAGE.sql    "$(year $4)" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./RCV_TRANSACTIONS_PRE_OUTAGE.sql             "$(year $4)" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_TXN_REQUEST_HDR_LINE_PRE_OUTAGE.sql     "$(year $4)" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./RCV_SHIPMENT_HDR_LINE_PRE_OUTAGE.sql        "$(year $4)" "'01-JAN'" "'31-MAR'"
 sqlplus -s ${LL} @./MTL_CYCLE_COUNT_ITEMS_PRE_OUTAGE.sql        "$(year $4)" "'01-JAN'" "'31-MAR'"
1 Like

Sometimes, you can impose a different time zone on the session, else subtract 4 hours from time using oracle time arithmetic.

Quoted quotes seems overkill, but if it works, great! I prefer to generate the input stream to one sqlplus command, with all the commands, "echo '... everything' | sqlplus ...." to save on connect fork exec overhead, and if there is any transactioning, you need to stay in one session. DB2 has a shadow process holding one session, so you can use this ugly, counterintuitive pragma, but as I recall every sqlplus is a new session. If you echo double quoted big string, you can use single on strings, just watch out for shell meta. I prefer to echo in single quotes, where little happens, and use '"'"' for each literal single quote. I am not sure if it is cheaper than <<, but << is very open to meta-shell expansion. Throw in lots of line feeds for beautification, and indentation if necessary. Do 'select scriptname from dual' or something before each script.

Use a wrapper script name in cron. Immediately wrap everything in "() >>log_file 2>&1" so everything is logged outside cron, and use date to put out time stamped run header+trailer messages.

date "+
========================================
%Y-%m-%d %H:%M:%S Start and End $$ ${0##*/} $* Be nice enough to say Fatal Error or Successful Finish
========================================"
1 Like

My OS is HP UX.

---------- Post updated at 11:21 AM ---------- Previous update was at 11:09 AM ----------

Gurus,

I sincerly apologize. I think I did not explain myself properly. Your recommendations are top notch.

I will be creating four of these scripts: dates for Q1, Q2, Q3, and Q4. Each script will be called once per day to convert data for the specified year based on which day of week it is. Monday we'll be converting for year 2005, Tuesday for 2006, etc. The year will not be passed in from cron. Actually no parameters will be passed from cron.
You have answered most of my question based on your responses anyway. I'm still a little confused as to how to code DOW to consider EDT offset.
Jim said to lose the Perl, ok. Then how does that get applied with the offset.

Thanks in advance for your help.

Why do you need 4 scripts? Create just one script and have it figure out what day of the it's running on and make determination based on that what year to run the 'conversion' for - should be pretty easy/basic to implement.

1 Like

VGersh,

Thanks for replying. The whole story is that we'll be executing each of the four scripts at different points during the day. We'll include each quarterly script as an entry in the cron.

The reason we're doing this is because our replication environment is spewing a boatload of alerts due to the volume of updates, not to mention, the load backing up.

Any additional help with the GMT-4 issue would be great.

Thanks.

Big operations especially transactions are a drag on any system. They lack locality of reference, run at disk speed not RAM and CACHE speeds. Do an hour, day, week at a time and wait between batches as long as the batch took for the interactive users, and let it chug. You could even collect all the rowids first, and then do 1024 rowids at a time. Think about it: you get 99+% of economy of scale doing 101 rows! Everything past that may be tiny or even a slowdown. If you make it a stored procedure or anonymous block, and let it run inside the engine, compile/plan time is eliminated. Then, there is locking . . . !

1 Like