KSH Script using SQLPlus will not commit - bash

function SQL_Command
{
result=`sqlplus -s /nolog <<!EOF
connect ********
whenever sqlerror exit failure
set pagesize 0
set feedback off
$1
$2
exit 0
!EOF`
}
So I have this function (above) and a few lines of codes beneath which are mostly inserts and updates, but anyhow they are not committed after execution.
I tried to add commit; but still it will not like literally be committed :c
function is used like this: SQL_Command "update ...." "commit;"
well at least that's what I've tried so far... anyone got any ideas :?
Thanks in advance!
brgds

I mean this: the heredoc terminator must not have any leading or trailing whitespace or any other characters*
function SQL_Command
{
result=$(sqlplus -s /nolog <<!EOF
connect ********
whenever sqlerror exit failure
set pagesize 0
set feedback off
$1
$2
exit 0
!EOF
)
}
*with one exception that you can read about in the bash manual.

Related

Call PL/SQL block in unix script

I am trying to call pl/sql block in unix script using sqlplus. I just tried to print a statement but nothing is getting printed and I am not getting any error as well.
Result=`sqlplus -s $TgtUsrID/$TgtPswd#$TgtServer <<eof
whenever sqlerror exit sql.sqlcode;
SET SERVEROUTPUT ON;
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World!');
END;
eof
`
current_time=`date`
echo " Script execution finished at $current_time"
Just need to prepend the variable(Result) with the dollar operator after the last EOF
along with an echo command such as
Result=`sqlplus -S /nolog << EOF
conn $TgtUsrID/$TgtPswd#$TgtServer
whenever sqlerror exit sql.sqlcode
set feedback off
SET SERVEROUTPUT ON;
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World!');
END;
/
EOF`
echo $Result
echo Script execution finished at $(date)
would yield such a result
Hello World!
Script execution finished at Tue Feb 14 00:15:51 +03 2021
where quotes for the description after the last echo is redundant, and prefer using connection with /nolog as being securer, since the password of the schema would be unveiled whenever ps -ef command issued in the current case.

Error Handling of SQLPlus from Bash - not working

I have read every relevant link on this issue and similar questions/answers, preveland answer is to first set whenever SQLERROR EXIT SQL.SQLCODE;
Only then do the query, and then inspect the SQL Plus return code using: ERRORCODE=$?
Here is a sample script:
GetAmountOfChunks()
{
export CHUNK_AMOUNT=`sqlplus -s $CONSTR<<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT SQL.SQLCODE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
/
SQL`
When ran it debug mode, it gives:
++ sqlplus -s USER/PASS#HOST/DB
+ export 'CHUNK_AMOUNT= select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ CHUNK_AMOUNT=' select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ ERRORCODE=0
+ '[' 0 -ne 0 ']'
As you can see, returned code is 0!
I expected if not 1476, then at least 196 (right most 8 bytes), but not 0 which indicates success!
Please help...
Thanks.
Your ERRORCODE is being set to zero because that's the exit code from the subshell you're running SQL*Plus is, viq the backticks. The exit code of the SQL*Plus process is 196 but you aren't capturing that, and it's not that easy to do that within a heredoc. The stdout from the process - which is what you are capturing - is not that exit code, it's the query and error message being printed. And even if you could capture it, I'm not sure how you'd distinguish between the 196 coming from an error, or from your actual query.
You could do something like running the query in a block that hides the error and prints either a default value or the actual calculated value, or only look at the last line of output and try to interpret that; but you'll still be fighting against it showing the command being run. SQL*Plus has set echo off but that doesn't do anything with an interactive session, which this still is with input redirection.
Another way to go is to create a script file and temporarily store the output:
echo "
set pages 0
set trim on
set feed off
set echo off
whenever SQLERROR EXIT FAILURE
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0;
" > /tmp/GetAmountOfChunks_$$.sql
sqlplus -s -l $CONSTR #/tmp/GetAmountOfChunks_$$.sql > /tmp/GetAmountOfChunks_$$.out
if [[ $? -eq 0 ]]; then
export CHUNK_AMOUNT=`cat /tmp/GetAmountOfChunks_$$.out`
else
# whatever you want to do on error; show output file? set default?
cat /tmp/GetAmountOfChunks_$$.out
fi
rm -f /tmp/GetAmountOfChunks_$$.sql /tmp/GetAmountOfChunks_$$.out
This creates a (process-specific) .sql file; executes that write the output (minus the statement, via set echo off) to a .out file; checks the SQL*Plus exit code; and if that is zero gets the result from the file.
As you hinted relying on SQL.SQLCODE to detect an error from your shell script is dangerous as you could get an error that wraps to zero, so I've used the generic FAILURE. If you need the real error code you can get it from the output file.
Another approach using a PL/SQL block:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
set serveroutput on;
declare
chunk_amount number;
begin
select 1/0 into chunk_amount from dual;
--SELECT COUNT(*) INTO chunk_amount FROM CNV_CHUNKS_PROC_STATUS;
dbms_output.put_line(chunk_amount);
exception
when others then
dbms_output.put_line(sqlcode);
end;
/
exit 0
SQL
exit $?`
ERRORCODE=$?
If the PL/SQL block runs then ERRORCODE will be zero and CHUNK_AMOUNT will be the calculated value if it's successful, or the SQL code if it throws an exception; since that will be negative (-1476 in your example) you can test that to see if it's expected, if you're only expecting positive values.
If the block can't run because of a syntax error or invalid credentials (notice the -l flag I snuck in) then ERRORCODE will be 1 and CHUNK_AMOUNT will have the error text, e.g. ERROR: ORA-12154: TNS:could not resolve the connect identifier... or whatever actually went wrong. The set -f stops a * in the error message being expanded into a file list from the current directory.
Or even more simply and closer to your original:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0
SQL
exit $?`
ERRORCODE=$?
and now ERRORCODE is 0 on success and CHUNK_AMOUNT has the calculated value on any error ERRORCODE is 1, you can test that directly, and the actual error is always in CHUNK_AMOUNT - but only as a string, you don't get -1476 this way.

How to fetch more than one column value from oracle select query to shell variable

I am trying to fetch a row with more than one column value to different shell variables. Infact I found that at a time all the column values can be stored to single shell variable. But how can I put those column values to seperate shell variables. Below is an example I am trying for time being
function sqlQuery {
sqlplus -S shiyas/********* <<'EOF'
set heading OFF termout ON trimout ON feedback OFF
set pagesize 0
SELECT name,open_mode from v$database;
EOF
}
OUTPUT="$( sqlQuery )"
echo $OUTPUT
Here I am getting the output as
ORCL READ WRITE
But my requirement is column values ORCL, READ WRITE should get assigned to different shell variable.
I tried the below of parsing.
echo "$OUTPUT" | while read name open_mode
but it was throwing unexpected end of file error.
-bash-3.2$ sh call_sql_col_val_1.sh
ORCL READ WRITE
call_sql_col_val_1.sh: line 18: syntax error: unexpected end of file
Please let me know what concept I can use to fetch a single row column values to different shell variables.
I do this via eval myself:
oracle#******:/*****> cat test.sh
#!/bin/bash
function sqlQuery {
sqlplus -S / as sysdba <<'EOF'
set heading OFF termout ON trimout ON feedback OFF
set pagesize 0
SELECT name,open_mode from v$database;
EOF
}
eval x=(`sqlQuery`)
NAME=${x[0]}
OPEN_MODE="${x[1]} ${x[2]}"
echo NAME IS $NAME
echo OPEN_MODE IS $OPEN_MODE
So we are running the same function you have above, passing it into x and running it through eval to handle the delimitation. Then you have an array and call call is as such: x[0] for the first item, for example.
Output is:
oracle#******:/******> sh test.sh
NAME IS ******
OPEN_MODE IS READ WRITE

Storing a query in a variable is adding a space in the string in ksh

I have this variable where I want to store a query that is inside a database.
Here is the variable
QUERY=`sqlplus -s $USER/$PASS <<EndSQL7
set pagesize 0
set feedback off
set verify off
set heading off
set echo off
select query
from generic_groupjob_table
where process_id = '${PROCESSID}'
and group_id = '${GROUPID}';
EXIT SQL.SQLCODE
EndSQL6`
when i echo the query, I see there is a space in the middle the string. So when I want to use that variable in another query I get the issue saying that i'm missing terminating quote due to that space. But that space is not supposed to be there.
sqlplus -s $DG_USER/$DG_PASS >> $LOGFILE <<EndSQL7
#generic_values.sql blah.txt '$QUERY'
EXIT SQL.SQLCODE
EndSQL7
The query will just return 1 column of values. What could be causing this unnecessary space?
I fixed the issue. It had to do with line feeder and carraige stop.
I added a parameter set linesize xxx and it fixed the space issue.
Try without any spaces you have for formatting purposes:
QUERY=`sqlplus -s $USER/$PASS <<EndSQL7
set pagesize 0
set feedback off
set verify off
set heading off
set echo off
select query
from generic_groupjob_table
where process_id = '${PROCESSID}'
and group_id = '${GROUPID}';
EXIT SQL.SQLCODE
EndSQL6`
try below
QUERY=sqlplus -s $USER/$PASS <<EndSQL7
set pagesize 0
set TRIM ON
set TRIMSPOOL ON
set feedback off
set verify off
set heading off
set echo off
select query
from generic_groupjob_table
where process_id = '${PROCESSID}'
and group_id = '${GROUPID}';
EXIT SQL.SQLCODE
EndSQL6

Ksh function to query Oracle with return values

Some time ago I wrote a small routine to run some quick n' dirty queries (and with that I mean it is not used for large queries) against an Oracle DB, but also wanted to do it a bit easier to parse errors. Follows:
# Executes the query
#
# Will execute a query contained in the variable named
# in the parameter $4 and store the result in the variable
# named in $5.
# In case of errors (even SQL related) the function should
# exit with status 1, making it possible to "if execQuery".
#
# #param $1 = User
# $2 = Pasword
# $3 = Tns Alias
# $4 = Name of the variable containing the query
# $5 = Name of the variable to hold the result
#
# #return query execution status
function execQuery {
typeset eSQLU=$1
typeset eSQLP=$2
typeset eSQLS=$3
typeset etQUERY=$4
eval typeset eQUERY=\$$etQUERY
typeset eQRES=$5
logMessageFile "DEBUG" "Query: $eQUERY"
typeset res=$(sqlplus -s $eSQLU/$eSQLP#$eSQLS <<EOF
set echo off newpage 0 space 0 pagesize 0 feed off head off verify off lines 999
WHENEVER SQLERROR EXIT 1
$eQUERY
exit;
EOF
)
[[ $? -gt 0 ]] && return 1 || eval "$eQRES=\"$res\""
}
The idea of this function is that later I could do something like:
query="select sysdate from dual;"
if execQuery $RAID_APP_PI_USR $RAID_APP_PI_PWD $RAID_APP_PI_SID query result ; then
echo $result
logMessageFile "INFO" "Inserts into XX successful."
else
logMessageFile "ERROR" "Error insertando XXX."
fi
It kinda works... A properly written query will do it fine, and the result variable is all correctly evaluated and all. The problem are the errors. If the query in that example was something like select * potato potato;, It'd still not yield the correct return value thus missing the error test.
I'm not particularly good with sqlplus nor ksh, probably just missing something obvious... Could someone lend me a hand here?
Thanks!
I believe $? is returning the exit status of the typeset command, not the sqlplus command.
It may be easier to output the results of your SQLPLUS statement to a file instead of into a variable. Then you could either read that file with grep, looking for an "ORA-" message, or check the exit status variable.
sqlplus -s $eSQLU/$eSQLP#$eSQLS > querylog.tmp <<EOF
set echo off newpage 0 space 0 pagesize 0 feed off head off verify off lines 999
WHENEVER SQLERROR EXIT 1
$eQUERY
exit;
EOF
echo $?

Resources