write bash function to drop user using sqlplus - linux

I have written a small bash script to delete some rows from a table and drop some users using sqlplus. When I put the code in the function it is giving "syntax error: unexpected end of file" error message. Below is the code. Please let me know how to fix it.
function reset_db
{
sqlplus user1/password1#${input} << eof
set timing off
set serveroutput on size 10000
set feedback off
spool logfile_$input.out
delete from table1 where component = 'XYZ';
delete from table2 where component = 'XYZ';
commit;
exit
eof
sqlplus dba_usr/dba_password#${input} << eof
set timing off
set serveroutput on size 10000
set feedback off
spool logfile_$input.out
drop user ABC cascade;
drop user DEF cascade;
drop user HIG cascade;
commit;
exit;
}

You're missing the eof at the end of your second sqlplus command. Change this:
exit;
}
to this:
exit;
eof
}
Incidentally, you don't actually need to call sqlplus two separate times; you can use its connect command to drop one connection and open a new one:
function reset_db
{
sqlplus user1/password1#${input} << eof
set timing off
set serveroutput on size 10000
set feedback off
spool logfile_$input.out
delete from table1 where component = 'XYZ';
delete from table2 where component = 'XYZ';
commit;
connect dba_usr/dba_password#${input}
drop user ABC cascade;
drop user DEF cascade;
drop user HIG cascade;
eof
}

Related

SQLPLUS embedded in linux script does not work as expected

I have the following script segment in a Linux script:
sqlplus /
<<QUERY_1
UPDATE BATCH_FILE SET BATCH_ID = 0 WHERE BATCH_ID = -1;
COMMIT;
exit
QUERY_1
I am expecting the update to occur and the script to exit sqlplus
What actually happens is the query is not executed, and the script exits leaving sqlplus logged into my database with a SQL> prompt. I can execute the statements from the prompt, but of course, that is not what I want to do.
My current version of Oracle is 12.2.0.1
The output of the HERE-document is intended for the std input of sqlplus, but for the shell a command should be on a single line. Adding a backslash will make the shell ignore the line-end, combining the two physical lines into one logical line:
sqlplus / \
<<QUERY_1
UPDATE BATCH_FILE SET BATCH_ID = 0 WHERE BATCH_ID = -1;
COMMIT;
exit
QUERY_1
Or just:
sqlplus / <<QUERY_1
UPDATE BATCH_FILE SET BATCH_ID = 0 WHERE BATCH_ID = -1;
COMMIT;
exit
QUERY_1

How to create parallel connections and queries to db in bash script

I have an oracle db on my Linux machine.
A single sql query (1 connection) via bash is as follows:
su - oracle
sqlplus <dbuser>/<dbpass>
select * from cat;
exit
I'm trying to run parallel queries via bash, the following script is for running 10000 connections in parallel (Correct me if i'm wrong):
for i in $(seq 1 10000); do echo "select * from <tableName>;" | sqlplus <dbuser>/<dbpass>&done
I would like to make this code more robust and flexible, for the sake of example i want to add a sleep between each of the following command:
Create a connection
Create a table (Unique to this connection, i as index for example)
Select data from the table
Close the connection
The following code is my attempt of doing so: (Not working)
for i in $(seq 1 10000);
do
echo "CREATE TABLE test+i (id NUMBER NOT NULL);"
sleep 2
echo "select * from test+i"
sleep 2
echo "DROP TABLE test+i" | sqlplus <dbuser>/<dbpass>&
done
1) Syntactically, how should i write it?
2) How can i know how many queries/connections succeeded and how many failed?
3) How can i know how many connections actually ran in parallel
1) you can use ( and ) to group command into subshells, and send them background:
for i in $(seq 1 10000);
do
echo "CREATE TABLE test_$i (id NUMBER NOT NULL);
!sleep 2
select * from test_$i;
!sleep 2
DROP TABLE test_$i;" | sqlplus <dbuser>/<dbpass> &
done
2) you can set up error handling after each sqlplus call (examine output or exit value)
echo "CREATE TABLE test_$i (id NUMBER NOT NULL);" | sqlplus <dbuser>/<dbpass> 2>&1 | grep -i error
3) you can use the jobs command to examine how many job is running in the background:
> sleep 100 &
[1] 31642
> jobs
[1]+ Running sleep 100 &
10000 jobs in parallel will often cause overflow. By setting 'WHENEVER SQLERROR EXIT SQL.SQLCODE' sqlplus will return an error, if the SQL fails. GNU Parallel can then re-run the query.
my.log will show if the query failed after rerunning 3 times.
doit() {
i=$1
(echo "WHENEVER SQLERROR EXIT SQL.SQLCODE CREATE TABLE test$i (id NUMBER NOT NULL);"
sleep 2
echo "WHENEVER SQLERROR EXIT SQL.SQLCODE select * from test$i;"
sleep 2
echo "WHENEVER SQLERROR EXIT SQL.SQLCODE DROP TABLE test$i;") |
sqlplus <dbuser>/<dbpass>
}
export -f doit
seq 1 10000 | parallel --joblog my.log -j0 --retries 3 doit

Shell script to fetch sql query data in csv file

Need to extract the below query data along with header in csv file using shell script.
Below is the query.
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode,NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UT)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj=0
UNION
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode, NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UTG)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj<>0
Could please let me know if below approach to fetch data using shell script is correct and script is correct.
#!/bin/bash
file="output.csv"
sqlplus -s username/password#Oracle_SID << EOF
SPOOL $file
select 'SourceIdentifier','SourceFileName','ProfitCentre2','PlantCode',
'tax_retur ReturnPeriod','document_number DocumentNumber','TO_CHAR(invoice_generation_date,'YYYY-MM-DD') Docume','Original','customer_name CustomerName','NVL(sns_pos,new_state_code)POS','PortCode','NEW_HSN_CODE HSNorSAC','(SGSATE+UTGSATE) Stat','(SGS+UT)StateUT','Userde' from dual
Union all
select 'TO_CHAR(SourceIdentifier)','TO_CHAR(SourceFileName)','TO_CHAR(ProfitCentre2)','TO_CHAR(PlantCode)',
'TO_CHAR(tax_retur ReturnPeriod)','TO_CHAR(document_number DocumentNumber)','TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume','TO_CHAR(Original)','TO_CHAR(customer_name CustomerName)','TO_CHAR(NVL(sns_pos,new_state_code)POS)','TO_CHAR(PortCode)','TO_CHAR(NEW_HSN_CODE HSNorSAC)','TO_CHAR((SGSATE+UTGSATE) Stat)','TO_CHAR((SGS+UT)StateUT)','TO_CHAR(Userde)' from
(SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode,NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UT)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj=0
UNION
SELECT SourceIdentifier,SourceFileName,ProfitCentre2,PlantCode,
tax_retur ReturnPeriod,document_number DocumentNumber,TO_CHAR(invoice_generation_date,'YYYY-MM-DD')
Docume,Original,customer_name CustomerName,NVL(sns_pos,new_state_code)POS,PortCode, NEW_HSN_CODE HSNorSAC,(SGSATE+UTGSATE) Stat,(SGS+UTG)StateUT,Userde FROM arbor.INV_REPO_FINA WHERE UPPER(document_type)='INV' AND UPPER(backout_flag)='VALID' AND new_gst_id_new IS NOT NULL AND new_charges<>0 AND taxable_adj<>0)
SPOOL OFF
EXIT
EOF
In short: the ; is missing from the end of the select statement.
Some unrequested advice:
I think spool will put extra stuff into your file (at least some new lines), a redirect is better, further the first line is not db-related:
echo "SourceIdentifier;SourceFileName;ProfitCentre2..." > $file
I recommend to generate the csv format right in the select query, later it will be more headache (you can escape there what you want):
$query = "select SourceIdentifier || ';' || SourceFileName || ';' || ProfitCentre2 ... ;"
So querying the DB (I think capital -S is the right one) plus for the formatting of the records (and maybe you want to format your columns too):
sqlplus -S username/password#Oracle_SID >> $file << EOF
set linesize 32767 pagesize 0 heading off
$query
EOF
For me this one is working but one empty line before first query and second query is coming. Empty line remove using awk command
#!/bin/bash
FILE="A.csv"
$ORACLE_HOME/bin/sqlplus -s username/password#Oracle_SID<<EOF
SET PAGESIZE 50000 COLSEP "," LINESIZE 20000 FEEDBACK OFF HEADING off
SPOOL $FILE
select 'TYPE_OF_CALL_V','SWITCH_CALL_TYPE_V','RECORD_TYPE_V','TARF_TYPE_V' from dual;
SELECT TYPE_OF_CALL_V,SWITCH_CALL_TYPE_V,RECORD_TYPE_V,TARF_TYPE_V FROM TABLE;
SPOOL OFF
EXIT
EOF
awk 'NF > 0' $FILE > out.txt
mv out.txt $FILE

sqlplus Input redirection on bash

New to sqlplus/bash scripting. I currently have a simple script that fetches some value in a table based on some ID values.
#do things. get login info. etc....
(cat<<HERE
set heading off;
select data_value from metadata where name='JOHN' and uniqueid in (1, 2, 3);
EOD
) | sqlplus -S $login
#do things.
What if instead of having to manually type of the ids (1, 2, 3, etc...), I do this:
#calls a script that gets the IDs from somewhere and outputs it in the correct format
./getIDscript > IDs
#do things. get login info. etc....
(cat<<HERE
set heading off;
select data_value from metadata where name='JOHN' and uniqueid in ($IDs);
EOD
) | sqlplus -S $login
#do things.
Would this work? I currently won't have access to the school lab for a few days so I can't test this out right now.
Is there a better and more efficient way of doing this?
Try this :
sqlplus -S /nolog <<_EOD1
WHENEVER SQLERROR EXIT SQL.SQLCODE
connect usr/xxx#db1
select 1 from dual
/
exit
_EOD1

Calling two functions one after other is failing in bash/sqlplus

I have two functions- ABC, XYZ. ABC deletes some rows in table1 as user1 and XYZ drops some users as DB User. First I am calling ABC and then XYZ. ABC function is being executed but at XYZ it is failing- "XYZ: command not found"
function ABC
{
sqlplus -s $ur1/$pwd#$SID << EOF
delete from table1 where row_name = 'A1';
delete from table2 where row_name = 'A2';
exit
EOF
}
function XYZ
{
sqlplus eip_dba/eip_dba$result#${input} << eof
set timing off
set serveroutput on size 10000
set feedback off
spool xyz_$input.out
drop user usr1 cascade;
drop user usr2 cascade;
drop user usr3 cascade;
commit;
exit
eof
}
ABC
XYZ
bash-3.2$ ./db_test.sh
2 rows deleted.
2 rows deleted.
./db_test.sh: line 100: XYZ: command not found
Please let me know what went wrong.
Thanks in advance.
Try removing the whitespace before EOF
function ABC
{
sqlplus -s $ur1/$pwd#$SID << EOF
delete from table1 where row_name = 'A1';
delete from table2 where row_name = 'A2';
exit
EOF
}
I tried this in a sample program and it fixed the problem.
The format of here-documents is:
<<WORD
here-document content ...
here-document content ...
here-document content ...
WORD
WORD can be any label you like, but the end marker must be the only thing on the line, no whitespaces before or after.
In your example functions you are using eof and EOF as labels, you should remove the space characters from in front of them so that they are really at the beginning of the line, like this:
function ABC
{
sqlplus -s $ur1/$pwd#$SID << EOF
delete from table1 where row_name = 'A1';
delete from table2 where row_name = 'A2';
exit
EOF
}
function XYZ
{
sqlplus eip_dba/eip_dba$result#${input} << eof
set timing off
# ... and so on ....
eof
}
That is, the ending EOF and eof are right at the beginning of the line, with no trailing spaces either.

Resources