how to passing variable from bash to sqlplus - linux

I have below code in bash:
#/!bin/bash
USERS=tom1,tom2,tom3
and I want to drop all users from my variable "USERS" via sqlplus
#/!bin/bash
USERS=tom1,tom2,tom3
sqlplus -s system/*** <<EOF
*some code*
DROP USER tom1 CASCADE;
DROP USER tom2 CASCADE;
DROP USER tom2 CASCADE;
EOF
pls help

Splitting in database using sql / plsql by using the USERS variable is complex and requires understanding of REGEXP functions and I will not recommend that to you. Moreover, it would also require Dynamic Sql to execute a drop query.
I would suggest you to split it within the shell script,create a script and execute it in sqlplus
USERS="tom1,tom2,tom3"
echo ${USERS} | tr ',' '\n' | while read word; do
echo "drop user $word;"
done >drop_users.sql
sqlplus -s system/pwd <<EOF
#some code
#drop_users.sql
EOF

Your code is OK except for DDL commands for Oracle DB which are derived from USERS parameter of the script file, call userDrop.sh. To make suitable relation with USERS parameter and DB, an extra file (drpUsr.sql) should be produced, and invoked inside EOF tags with an # sign prefixing.
Let's edit by vi command :
$ vi userDrop.sh
#!/bin/bash
USERS=tom1,tom2,tom3
IFS=',' read -ra usr <<< "$USERS" #--here IFS(internal field separator) is ','
for i in "${usr[#]}"; do
echo "drop user "$i" cascade;"
done > drpUsr.sql
#--to drop a user a privileged user sys or system needed.
sqlplus / as sysdba <<EOF
#drpUsr.sql;
exit;
EOF
Call as
$ . userDrop.sh
and do not forget to come back to command prompt by an exit command of DB.

Related

How to call Oracle SQL query using bash shell script

How to call a sql query using bash shell script. I tried the below but seems there is some syntax error:
#!/bin/sh
LogDir='/albt/dev/test1/test2/logs' # log file
USER='test' #Enter Oracle DB User name
PASSWORD='test' #Enter Oracle DB Password
SID='test' #Enter SID
sqlplus -s << EOF > ${LogDir}/sql.log
${DB_USER_NAME}/${DB_PASSWORD}#${DB_SID}
SELECT count(1) FROM dual; # SQL script here to get executed
EOF
var=$(SELECT count(1) FROM dual)
I'm getting - unexpected token error
#!/bin/sh
user="test"
pass="test"
var="$1"
sqlplus -S $user/$pass <<EOF
SELECT * FROM tableName WHERE username=$var;
exit;
EOF
I'm getting - sqlplus: command not found -- when I run the above script
Can anyone guide me?
In your first script, one error is in the use of count(1). The whole line is
var=$(SELECT count(1) FROM dual)
This means that the shell is supposed to execute a program named SELECT with the parameters count(1), FROM and dual, and stores its stdout into the variable var. I think you want instead to feed a SELECT command into sqlplus, i.e. something like
var=$(sqlplus .... )
In your second script, the error message simply means that sqlplus can not be found in your path. Either add it to the PATH or provide the absolute path to the command explicitly.

"Nothing in SQL buffer to run." message on executing a shell script

I am running the following shell script which calls a .SQL file, that contains a list of DELETE statements. On executing ./delete_crr_input_purge.sh, I get the following message "Nothing in SQL buffer to run.". The .SQL file gets executed anyway but what is wrong with my code in the shell script?
#!/bin/ksh
#
# #(#)Copyright All Rights Reserved.
# #(#) $Id: run_drm_utility.sh $
# Setup common environment
. `dirname $0`/db_env.sh
cd `dirname $0`
echo "Enter the SHBA Atomic DB User Name:"
read USERNAME
echo "Enter the SHBA Atomic DB User Password:"
read PASS
cnt=`sqlplus -s /nolog <<-EOF
WHENEVER OSERROR EXIT 9;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
connect $USERNAME/$PASS#$ORACLE_SID
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
#delete_crr_input_purge.sql;
commit;
EOF`
echo [$cnt]
return $?
I was able to fix this error by removing comments and occurrences of "/" from my .SQL file.
Also, I made sure that each of my SQL statements were in one line, one below the other. Also, no commit statement inside the .SQL file.

storing Output of plsql query in shell script

I'm not getting any output to my FILE for query. while I'm running in oracle I can see the counts.
Can someone please let me know what am I doing wrong?
#!/bin/bash
ORACLE_HOME=*path*
TNS_ADMIN=*path*
export ORACLE_HOME
export TNS_ADMIN
FILE="/tmp/score_cnt.txt"
sqlplus -S user/pass#service<< EOF
spool $FILE
select count(*) from score_tbl
spool off
exit;
EOF
Seems like passing the *nix variable to SQL*Plus is messing the things around here.
As far as I understand, you wish to pass the file name in the script, then the easiest mechanism would be to define it as SPOOL File directly (instead of getting it parametrized).
Moreover you can add some really useful SET parameters to beautify the output.
sqlplus -S user/pass#service << EOF
SET LINESIZE 32000
SET PAGESIZE 0
SET TRIMSPOOL ON
SET TRIMOUT ON
SET WRAP OFF
SET TERMOUT OFF
spool /tmp/score_cnt.txt
select count(*) from score_tbl;
spool off
EOF
PS - EOF doesn't require additional exit in sqlplus & select
statement must end with a ;

how to use /dev/null for bash command

I am using below command to get result for my SQL query.
su - postgres -c 'psql -d dbname' with stdin "COPY ( my SQL query ) TO STDOUT WITH CSV HEADER"
This works fine on my server but on different machine it is printing bash warning with output of SQL query.
For example -
/etc/profile: line 46: HISTSIZE: readonly variable
/etc/profile: line 50: HISTCONTROL: readonly variable
/etc/profile.d/20-tmout.sh: line 1: TMOUT: readonly variable
/etc/profile.d/history.sh: line 6: hcmnt_tty: readonly variable
name
abc
Please let me know anyway so that I can skip above warning messages and only get data.
If I would like to use /dev/null in this case how to modify above command to get data only.
if what you mean is "how to discard only error output?", the way to go is to redirect the standard error stream to oblivion (/dev/null), like so:
your-command 2>/dev/null
that way, if the command outputs data to standard out, it passes through, but any output to the standard error socket is discarded, so you won't see these error messages.
by the way, 2 here is a shorthand file descriptor for the standard error.
Sorry this is untested, but I hit this same error, your db session isn't read/write. You can echo the statements to psql to force a proper session as follows. I'm unsure as to how stdin may be effected
echo 'SET TRANSACTION READ WRITE; SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE ; COPY ( my SQL query ) TO STDOUT WITH CSV HEADER' | su - postgres -c 'psql -d dbname' with stdin
caution - bash hack
su - postgres -c 'psql -d dbname' with stdin "COPY ( my SQL query ) TO STDOUT WITH CSV HEADER" | grep -v "readonly"

Replace variable in bash file using sed - output lags

I'm trying to write a bash script that search and replace a specific
user input saved in config.sh using sed. This does work; however it
only works partially as shown below.
config.sh
#!/bin/bash
#
#UserName to be deleted
delUserName=""
#Source
delUserSrc=/Users/"$delUserName"
#Destination
delUserDest=/Users/John/BackUp/"$delUserName"/"$delUserName".zip
main.sh
#!/bin/bash
#
source scripts/config.sh
echo -e "\nEnter user you wish to delete: \c"
read -r UserName
sed -i '' -e "s/delUserName=.*/delUserName=$UserName/g" scripts/config.sh
echo -e "delUserName: $delUserName"
echo -e "delUserSrc: $delUserSrc"
echo -e "delUserDest: $delUserDest"
output1:
Enter user you wish to delete: Test
delUserName:
delUserSrc:/Users/
delUserDest:/Users/John/BackUp/ / .zip
output2:
Enter user you wish to delete: Test1
delUserName:Test
delUserSrc:/Users/Test
delUserDest:/Users/John/BackUp/Test/Test.zip
output3:
Enter user you wish to delete: Test1
delUserName:Test1
delUserSrc:/Users/Test1
delUserDest:/Users/John/BackUp/Test1/Test1.zip
expected output1:
Enter user you wish to delete: Test
delUserName:Test
delUserSrc:/Users/Test
delUserDest:/Users/John/BackUp/Test/Test.zip
expected output2:
Enter user you wish to delete: Test1
delUserName:Test1
delUserSrc:/Users/Test1
delUserDest:/Users/John/BackUp/Test1/Test1.zip
The script lags. sed instantaneously changed the value for $delUserName BUT The proper values for $delUserName, $delUserSrc, and $delUserDest only echo on the 2nd run. The scripts run well when all variables are in main.sh except i have to do it this way. Save the user input into $UserName. Any idea why the values don't show when run the 1st time?
Thanks
Here is what I think is happening.
The sed command replaces text in files. It does not modify the value of variables in memory. These values are assigned when you source config.sh.
So right after your sed line, you need to put this line :
source scripts/config.sh
It is the same line as above in your script. This is required there also so that your newly replaced values will be loaded in the variables so that you can display them. Once the new values are loaded in memory, then the echo statements will be able to expand the variables to that new value.

Resources