How to store sql query output in variable in shell script - bash

I am trying to store the value of sql query output in a variable using shell script.
size=`${PATH_TO_CLIENT}sqlplus $IMPUSER/$IMPPWD#$ENDPOINT<< EOF
select owner, sum(bytes)/1024/1024/1024 Size_GB from dba_segments where owner = 'XXXX' group by owner;
exit;
EOF`
echo "Total data is ${size}"
The output I am getting is
**Total data is**
SQL*Plus: Release 21.0.0.0.0 - Production on Fri May 14 11:06:42 2021
Version 21.1.0.0.0
Copyright (c) 1982, 2020, Oracle. All rights reserved.
Last Successful login time: Fri May 14 2021 11:01:02 -04:00
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.8.0.0.0
SQL>
OWNER
--------------------------------------------------------------------------------
SIZE_GB
----------
XXXXXXX
12.2345
SQL> Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.8.0.0.0
Inside the variable full connection string and sql query output all are getting stored. I just want to get value like $size=12.2345 Please tell me how to get that

The size value might be assigned to the current variable through use of the following code block
size=$(sqlplus -S /nolog << EOF
conn $IMPUSER/$IMPPWD#$ENDPOINT
whenever sqlerror exit sql.sqlcode
SET PAGES 0
SELECT SUM(bytes)/1024/1024/1024 FROM dba_segments WHERE owner = 'XXXX';
EOF
)
echo "Total data is "$size
where
keeping owner column and group by clause are redundant as
returning only one column value for a single schema
no need to alias the calculated value as not needed for the returning result while hiding the column title through use of SET PAGES 0 command
using direct connection is not safe, but use sqlplus -S /nolog before
schema connection in order to hide the password while listed by
anbody through ps command.

You can use this:
size=`${PATH_TO_CLIENT}sqlplus -s $IMPUSER/$IMPPWD#$ENDPOINT <<EOF
set echo off
set feedback off
set heading off
set pages 0
select sum(bytes)/1024/1024/1024 Size_GB from dba_segments where owner = 'SYS';
exit;
EOF`
echo "Total data is ${size}"

If the output is consistent with newlines, you could use:
size=`${PATH_TO_CLIENT}sqlplus $IMPUSER/$IMPPWD#$ENDPOINT<< EOF | sed -n '/^\s*SIZE_GB$/{n;n;n;p}'
select owner, sum(bytes)/1024/1024/1024 Size_GB from dba_segments where owner = 'XXXX' group by owner;
exit;
EOF`
It will return the third line after line which contains 'SIZE_GB'.

Related

I am getting ORA-04043: object does not exist error in SQL loader. When command is being executed getting table does not exist error

CSV FILE CONTENT
portal,,
ex portal,,
,,
i_id,i_name,risk
1,a,aa
2,b,bb
3,c,cc
4,d,dd
5,e,ee
6,f,ff
7,g,gg
8,h,hh
9,i,ii
10,j,jj
CONTROL FILE CONTENT
options (
skip=4,
PARALLEL=true,
DIRECT=true
)
LOAD DATA
INFILE 'E:\sqlloader\testfile.csv'
APPEND
INTO TABLE LOADER_TAB
FIELDS TERMINATED BY ","
(
i_id,
i_name,
risk
)
I am getting object does not exist but table name does exist in the schema system
select tab.owner, tab.STATUS
from dba_tables tab
where tab.TABLE_NAME = 'LOADER_TAB';
Also tried by giving scema_name.table_name but no luck.
options (
skip=4,
PARALLEL=true,
DIRECT=true
)
LOAD DATA
INFILE 'E:\sqlloader\testfile.csv'
APPEND
INTO TABLE SYSTEM.LOADER_TAB
FIELDS TERMINATED BY ","
(
i_id,
i_name,
risk
)
Can someone help me on this I had searched for the answer and did all possible way but not getting the solution.
You're almost there - here's a top to bottom run of the code, the only change being I've created a schema to hold the table and the path names for the CSV file. So follow the demo below and if yours does not get the same result, edit the question with the full output similar to below. Also, if you still get issues, try it without DIRECT/PARALLEL which will help us dig deeper into the "why".
SQL> create user myuser identified by mypassword;
User created.
SQL> alter user myuser quota unlimited on users;
User altered.
SQL> grant connect, resource to myuser;
Grant succeeded.
SQL> create table myuser.LOADER_TAB(i_id number(10),i_name varchar2(30),risk varchar2(30));
Table created.
x:\tmp>sqlldr userid=myuser/mypassword#db19_pdb1 control=loader.ctl
SQL*Loader: Release 19.0.0.0.0 - Production on Tue Nov 2 11:38:58 2021
Version 19.12.0.0.0
Copyright (c) 1982, 2021, Oracle and/or its affiliates. All rights reserved.
Path used: Direct
Load completed - logical record count 10.
Table LOADER_TAB:
10 Rows successfully loaded.
Check the log file:
loader.log
for more information about the load.
x:\tmp>sqlplus myuser/mypassword#db19_pdb1
SQL*Plus: Release 19.0.0.0.0 - Production on Tue Nov 2 11:39:21 2021
Version 19.12.0.0.0
Copyright (c) 1982, 2021, Oracle. All rights reserved.
Last Successful login time: Tue Nov 02 2021 11:38:58 +08:00
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.12.0.0.0
SQL> select * from loader_tab;
I_ID I_NAME RISK
---------- ------------------------------ ------------------------------
1 a aa
2 b bb
3 c cc
4 d dd
5 e ee
6 f ff
7 g gg
8 h hh
9 i ii
10 j jj
10 rows selected.

Is it possible to pass a single query to SQLplus?

I regularly need to run a single query on some table in one of my DBs and I would rather not have to create a file and call it as a script and everything if I don't have to.
I would like to be able to send the query directly to sqlplus as a string like this perhaps
sqlplus user/pass#hostname:port/service "select * from table"
instead of having to create a file that holds only that one query and call it with
sqlplus user/pass#hostname:port/service #filename
does anyone know if this is possible?
In addition to mathguy answer, with linux shells,
you can use the operator here-string like this:
sqlplus user/pass#hostname:port/service <<< 'select * from table;'
Don't forget the semi-colon at the end of your query.
I believe the sqlplus command doesn't accept a SQL statement (as a string) as a command-line parameter. You can run sqlplus either interactively or in batch (giving a .sql file as input).
However, you can do something like what you are asking, using operating system facilities. I don't know how this might work in Windows, but in Unix/Linux you can use a here document. Something like this: (I masked my password and my machine name for privacy, but otherwise it's a screenshot showing the command and its output)
[oracle#******** ~]$ sqlplus mathguy/********#orclpdb <<EOF
> select empno, ename, sal
> from scott.emp
> where deptno = 30;
> EOF
SQL*Plus: Release 12.2.0.1.0 Production on Fri Mar 26 15:15:30 2021
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Last Successful login time: Fri Mar 26 2021 15:14:40 -07:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> 2 3
EMPNO ENAME SAL
---------- ---------- ----------
7499 ALLEN 1600
7521 WARD 1250
7654 MARTIN 1250
7698 BLAKE 2850
7844 TURNER 1500
7900 JAMES 950
6 rows selected.
SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0
- 64bit Production
[oracle#******** ~]$
Never ever enter your credentials next to sqlplus command but use /nolog option through a variable assignment in order to unveil them whenever ps command issued by the others such as
rec=$(sqlplus -S /nolog << EOF
conn un/pwd#mydb
set pages 1001
set linesize 500
set feedback off
SELECT * FROM tab;
exit
EOF
)
echo $rec

sqlldr error in Oracle

Currently, I am using sqlldr userid= {user}/{pass}#{SID} to load the file into database, and this comment is in a bash file.
The password is generated by a third lib framework.
But, I found that sometimes I got the following error,
export TNS_ADMIN=/opt/config/uat/
export PATH=$PATH:$ORACLE_HOME/bin
sqlldr userid=M_UAT/YAu8D=5r#My_UAT
ERR>LRM-00116: syntax error at 'M_UAT/YAu8D' following '='
I found that there is a special character = in the password,
I checked something, seems sqlplus can avoid this exception by userid= ={user}/\"{pass}\"#{SID}
But sqlldr cannot.
Does anyone have an idea here?
sqlplus makes a connection with the username and password in quotes. The sqlloader(sqlldr) connects to the database only if the name is written without quotes.
The password can contain #!= characters only in quotation marks, for example
password=\"YAu8D=5r\"
password=\"#!YAu8D=5r#\"
Example 1
username=HR
password=\"YAu8D=5r\"
Change password
oracle#esmd:~> sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Mon Jul 2 13:39:10 2018
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Release 11.2.0.3.0 - 64bit Production
SQL> alter user hr identified by "YAu8D=5r" ;
User altered.
SQL> exit
Test connect sqlplus
#!/bin/sh
username=\"HR\"
password=\"YAu8D=5r\"
echo username: $username
echo password: $password
testoutput=$(sqlplus -s $username/$password << EOF
set pagesize 0 feedback off verify off heading off echo off;
show user
SELECT to_char(sysdate,'DD-MM-YYYY HH24:MI')||' Test passed' from dual
#ulcase1.sql
exit;
EOF
)
echo $testoutput
oracle#esmd:~> ./test_Upper_case2.sh
username: "HR"
password: "YAu8D=5r"
USER is "HR"
Test SQL*loader script test_sqlldr.sh
oracle#esmd:~> more test_sqlldr.sh
#!/bin/sh
username=hr
password=\"YAu8D=5r\"
sqlldr userid=$username/$password control=ulcase2.ctl log=log.log
Test SQL*loader
oracle#esmd:~> ./test_sqlldr.sh
SQL*Loader: Release 11.2.0.3.0 - Production on Mon Jul 2 13:46:29 2018
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Commit point reached - logical record count 7
oracle#esmd:~>
Test network connection sqlldr
oracle#esmd:~> more test_sqlldr.sh
#!/bin/sh
username=hr
password=\"YAu8D=5r\"
sqlldr userid=$username/$password#esmd control=ulcase2.ctl log=log.log
oracle#esmd:~> ./test_sqlldr.sh
SQL*Loader: Release 11.2.0.3.0 - Production on Mon Jul 2 13:53:24 2018
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Commit point reached - logical record count 7
Example 2
username=HR
password=\"#!YAu8D=5r#\"
Script for connection testing sqlplus
#!/bin/sh
username=HR
password=\"#!YAu8D=5r#\"
echo username: $username
echo password: $password
testoutput=$(sqlplus -s $username/$password << EOF
set pagesize 0 feedback off verify off heading off echo off;
show user
SELECT to_char(sysdate,'DD-MM-YYYY HH24:MI')||' Test passed' from dual;
#ulcase1.sql
exit;
EOF
)
echo $testoutput
Test connect sqlplus
oracle#esmd:~> ./test_Upper_case2.sh
username: "HR"
password: "#!YAu8D=5r#"
USER is "HR" 03-07-2018 12:44 Test passed
Test SQL*loader script test_sqlldr.sh
#!/bin/sh
username=HR
password=\"#!YAu8D=5r#\"
sqlldr userid=$username/$password control=ulcase2.ctl log=log.log
Test SQL*loader
oracle#esmd:~> ./test_sqlldr.sh
SQL*Loader: Release 11.2.0.3.0 - Production on Tue Jul 3 12:48:53 2018
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Commit point reached - logical record count 7
Example 3
username=\"HR\"
password=\"#!YAu8D=5r#\"
Script for connection testing sqlplus
#!/bin/sh
username=\"HR\"
password=\"#!YAu8D=5r#\"
echo username: $username
echo password: $password
testoutput=$(sqlplus -s $username/$password << EOF
set pagesize 0 feedback off verify off heading off echo off;
show user
SELECT to_char(sysdate,'DD-MM-YYYY HH24:MI')||' Test passed' from dual;
#ulcase1.sql
exit;
EOF
)
echo $testoutput
Test connect sqlplus
oracle#esmd:~> ./test_Upper_case2.sh
username: "HR"
password: "#!YAu8D=5r#"
USER is "HR" 03-07-2018 12:51 Test passed
oracle#esmd:~> more test_sqlldr.sh
#!/bin/sh
username=\"HR\"
password=\"#!YAu8D=5r#\"
sqlldr userid=$username/$password control=ulcase2.ctl log=log.log
Test SQL*loader
oracle#esmd:~> ./test_sqlldr.sh
LRM-00112: multiple values not allowed for parameter 'userid'
SQL*Loader: Release 11.2.0.3.0 - Production on Tue Jul 3 12:54:42 2018
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
SQL*Loader-100: Syntax error on command-line

How to Access Oracle Table through bash when it's a new create table

I have a simple script in bash that just return the count of a given table
The trow command through bash its like that
user>bash Bash_Script.bsh -T MyTableTthatAlreadyExists
After the conections parameters it just do that:
SQLSTRING="SELECT COUNT(*) FROM $SYBTAB;"
BATCH_ARGS=`sqlplus -S /nolog <<SQL | tail -1
connect $ORCL_USR/$ORCL_PWD#$ORCL_TNS;
alter session set nls_date_format='YYYYMMDD';
set pagesize 0 long 4096 linesize 32767 feed off head off;
$SQLSTRING
quit;
SQL`
echo "$BATCH_ARGS"
And it works. Yest it works, it returns the nummer of rows of my table.
The problem come when I create a new table MyNewTable
- The table exists in Oracle
so when I do in SQL Developer
select count(*) from MyNewTable;
return the correct nummer.
But when I throw again the unix command. It doesnt work, it doesnt return anything
user>bash Bash_Script.bsh -T MyNewTable --> return nothing
I wonder myself what I m missing, wat I m not taking account.
I thounk about Grant privileges but they both haven the same.
can anyone here help me ?
Thanks in advance, Enrique
Your script is only getting the last line of output from SQL*Plus
BATCH_ARGS=`sqlplus -S /nolog <<SQL | tail -1
If you remove the tail part:
BATCH_ARGS=`sqlplus -S /nolog <<SQL
then you'll see what is actually happening. With a table that exists, with that modification I see:
user>bash Bash_Script.bsh -T MyTableTthatAlreadyExists
Session altered.
1815
and with a table that does not exist I see:
user>bash Bash_Script.bsh -T MyNewTable
Session altered.
SELECT COUNT(*) FROM t43
*
ERROR at line 1:
ORA-00942: table or view does not exist
It seems you are seeing ORA-01031: insufficient privileges, so the user you are connecting as needs to have select privileges granted for the new table.
As you only want the actual count, if you swap the order of the alter and set clauses the Session altered. message will also be suppressed as feedback will be switched off by then:
BATCH_ARGS=`sqlplus -S /nolog <<SQL
connect $ORCL_USR/$ORCL_PWD#$ORCL_TNS;
set pagesize 0 long 4096 linesize 32767 feed off head off;
alter session set nls_date_format='YYYYMMDD';
$SQLSTRING
quit;
SQL`
and you'd then see, for an existing table, just:
user>bash Bash_Script.bsh -T MyTableTthatAlreadyExists
1815
making the tail unnecessary anyway.

sqlplus Dynamic Spool File Name

I need to give the spool file name dynamically and I have to pass the parameters when I call sqlplus. Below is what I tried
echo exit | sqlplus "{{ Oracle_username }}/ {{ Oracle_pwd}} #(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host={{ Oracle_HostName }} )(Port=1521))(CONNECT_DATA=(SID= {{Oracle_SID }})))" #Script.sql 'AppName' 'DatabaseName' 'ObjectType'
Over here I tried to pass App Name, Database Name and Object Type dynamically. Prior to running SQLPLUS step, I create folders dynamically (App Name , Database Name , Object Type are all folders and it will vary depending on each application) .Below is how my script.sql looks like :
SPOOL &&AppName/&&DatabaseName/&&ObjectType/Output.csv
<<SQL Script>>
SPOOL OFF
This doenst work . Can someone tell me what needs to be changed.
You are passing the values you want to form your spool file path and name as arguments to your script, but you need to refer to them as positional parameters:
SPOOL &1/&2/&3/Output.csv
Or if you're going to reuse them for something else you could define your own variable, set from the positional parameters:
DEFINE AppName=&1
DEFINE DatabaseName=&2
DEFINE ObjectType=&3
SPOOL &&AppName/&&DatabaseName/&&ObjectType/Output.csv
The spool file path will be relative to the directory you're in when you run the script. If that isn't what you want then put the root before the first substitution variable in the spool command, whichever form you use.
You could also include the exit in your .sql file so you don't have to echo it in; and you could use a TNS alias instead of passing all of the connection information on the command line - or if you can use a service name instead of a SID, you could use the easy connect syntax which is a bit simpler:
sqlplus username/password#//hostname:1521/service_name #Script.sql 'AppName' 'DatabaseName' 'ObjectType'
set your appname,dbname,objecttype's as environmental variables and then Try like below
[oracle#ct-myhost-02 ~]$ export app_name=/stage
[oracle#ct-myhost-02 ~]$ export database_name=PSES
[oracle#ct-myhost-02 ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Wed Feb 1 12:04:08 2017
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> spool $app_name/$database_name/out.csv
SQL> select * from dual;
D
-
X
SQL> spool off;
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
[oracle#ct-myhost-02 ~]$ ls -l /stage/PSES/out.csv
-rw-r-----. 1 oracle oinstall 286 Feb 1 12:04 /stage/PSES/out.csv

Resources