SQLPLUS connection to different dbs - oracle

Hello i want to connect to following dbs in loop and execute statements on each:
conn support/support#sp0666to
conn support/support#sp0667to
conn support/support#sp0668to
Is there any way to do this in sqlplus?
Thank you for your answers in advance!

Create one script (doWork.sql) that contains the majority of what you want to do:
conn &1/&2#&3
select EMPLOYEE, AUTHORIZED, TIME, DAT, WORKSTATION
from EMPLOYEE
where status = 25;
In a separate script (goToWork.sql):
set lines 1500 pages 10000
set colsep ';'
set sqlprompt ''
set heading on
set headsep off
set newpage none column tm new_value file_time noprint
select to_char(sysdate, 'DDMMYYYY_HH24.MI') tm from dual;
accept user
accept pass
spool C:\Users\NANCHEV\Desktop\parked.csv
##doWork &user &pass sp0666to
##doWork &user &pass sp0667to
##doWork &user &pass sp0668to
spool off;
exit
If you want separate files, then move the two spool commands to the doWork.sql file.

Assuming you want to run the same set of queries for each database, I'd create a script file (e.g. main_statements.sql) containing those statements.
Then, if the list of databases was static, I'd create a second script file (e.g. run_me.sql) in the same directory, with contents along the lines of:
connect &&user/&&password#db1
##main_statements.sql
connect &&user/&&password#db2
##main_statements.sql
connect &&user/&&password#db3
##main_statements.sql
...
If, however, the databases are static but the list is contained in a database somewhere, then I'd write a script (e.g. run_me.sql) that generates a script, something like:
set echo off
set feedback off
set verify off
spool databases_to_run_through.sql
select 'connect '||username||'/'||password||'#'||database_name||chr(10)||
'##main_statements.sql'
from list_of_databases_to_query;
spool off;
##databases.run_through.sql
N.B. untested. Also, I have assumed that your table contains the usernames and passwords for each db that needs to be connected to; if that's not the case, you'll have to work out how to handle them; maybe they're all the same (in which case, you can hardcode them - or better yet, use substitution variables (e.g. &&username) to avoid having to store them in a plain file. You'd then have to enter them at runtime.
You'll also need to run the script from the same directory, otherwise you could end up with the generated script not being created in the same directory as your main_statements.sql equivalent script.

Yes it's possible, you can use oracle DBLink to connect to different dbs just like your example.

Related

Oracle RDS Logminer ORA-01291 Missing Log File?

I have an Oracle RDS database I manage, and I need to be able to pull changes from the database for replication to another system. Once connect to the database, below is the commands I run.
EXEC rdsadmin.rdsadmin_util.create_directory(p_directory_name => 'logminerlogs');
set heading off;
set echo off;
set space 0;
set pagesize 0;
set linesize 10000;
set termout off;
set trimout on;
SET TRIMSPOOL ON;
set feedback off;
set newpage NONE;
set define on;
exec dbms_stats.gather_dictionary_stats;
EXEC rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD','PRIMARY KEY');
EXEC rdsadmin.rdsadmin_util.alter_supplemental_logging('ADD','UNIQUE');
BEGIN
dbms_logmnr.add_logfile(
logfilename=> 'rdsdbdata/db/ORCL_A/arch?redolog-99999-9-9999999999.arc');
*** REPEAT for all redo logs ***
END
/
EXECUTE dbms_logmnr.start_logmnr(STARTTIME=>SYSDATE-1,ENDDATE=>SYSDATE,OPTIONS=>DBMS_LOGMNR.DICT_FROM_REDO_LOGS+DBMS_LOGMNR.COMMITTED_DATA_ONLY+DBMS_LOGMNR.PRINT_PRETTY_SQL);
Doing all of that gives me the error
ORA-01291: missing log file
ORA-06512: at "SYS.DBMS_LOGMNR", line 72
ORA-06512: at line 1
I get all of the 'arc' files by querying
SELECT name FROM v$archived_log WHERE first_time > SYSDATE-1 and first_time < systdate ORDER BY 1;
I ran all of these scripts once and I was able to query v$logmnr_contents and get the results I wanted. When I opened another SQLPlus window and ran all of the scripts again, I get the error of Missing Log File mentioned above.
I'm not exactly sure what I am doing wrong here. I have also tried
DBMS_LOGMNR_D.BUILD(dictionary_filename=>'lgmnrdict.ora',dictionary_location=>'LOGMNRLOGS');
where LOGMNRLOGS is a dictionary folder I created previously, and then instead of the redologs when calling add_logfile I point to the 4 onlinelogs .log files that exist on the database and then run command
EXECUTE DBMS_LOGMNR.START_LOGMNR(dictfilename=>'/rdsdbdata/userdirs/o1/logmnrdict.ora');
This will start Logminer, but when I make any changes and commit to the database, when I query v$logmnr_contents those changes are not being returned.
I realize I might be rambling at this point, but I feel like I am very close to the solution; I'm just missing something. Any help is appreciated.
The problem was that for each add_logfile command, I was setting options for dbms_logmnr.new for each rather than for the first and all remaining redologs using dbms_logmnr.addfile.

Export data as XSV from oracle

I want to export some data (i.e. some queries results') from an old oracle database into a file, values separated with a specified character or sequence of characters. A CSV file is an example.
Only integers, varchars (without newline included), dates, other basic values (?) into result set, so no LOBs or another fancy stuff. Just plain data, NO PADDING, NO WRAPPING, fields separated and maybe enclosed.
Practicaly, I'm looking for a simple "SELECT ... INTO OUTFILE FIELDS TERMINATED BY ... [OPTIONALLY] ENCLOSED BY 'char'" from mysql, but for Oracle.
I tried to use sqlplus, but any program should be ok, as long as it runs on linux console and it's not java based :-P.
Unfortunately I cannot use "SET SQLFORMAT csv", seems to be not supported.
So far I've got best results with something like:
printf "set echo off newpage 0 pagesize 0 arraysize 5000 feed off head off trimspool on trimout on\nselect field1 || '|' || field2 from table;" | sqlplus -S database > output_file
Set arraysize 5000 (maximum) gives the best performance, unfortunately wraps the result if lines are longer than 80 chars.
Set linesize 30000 (or even 32767) cancels wrapping, unfortunately the performance becomes horrible. I don't want to specify a maximum linesize for each query (calculating maximum size for each field in result), hoping that performance will rise.
After reading tons of answers I'm still not getting close to a solution that should be both CORRECT and PERFORMANT. My next call will be writing a php file to do the job, but it's a nonsense, IMHO using the default application sqlplus should give the best performances ...
Any ideas ?
I can't tell whether this set of SET commands will help (I use it, usually), but - try it.
set termout off
set trimspool on
set echo off
set verify off
set autoprint off
set serveroutput off
set arraysize 1000
set pagesize 0
set linesize 100
set long 10000
set numwidth 10
set feedback off
set colsep ';'
col empno format 99999
col ename format a10
col sal format 999G990
spool emp.txt
select empno, ename, sal from emp;
spool off
At the bottom, you can see some COL formattings; remove it if you don't need it.
Don't set linesize to that high number (30.000) if you don't really need it.
Also, there's the set colsep ';' which will separate columns by that separator (semi-colon in this example; can be any other character, such as | you mentioned).
In order to speed up spool:
set termout off
set trimspool on
run it on server, not on the client PC
Ok, for everyone that had this problem, here is the answer:
Make sure you have at least oracle client 12.2 installed.
If not, you can extract the files from instantclient-basic-linux.x64-12.2.0.1.0.zip (library files) and from jar archives from sqlplus related directories from linuxx64_12201_client.zip (client/stage/Components/oracle.sqlplus*). Those two zips are available to download for free (registration required) at oracle download site. I didn't want to install that version of the client because it could mixed up with local installed one. It's kind of an ugly hack, but at least no file on system was modified.
From 12.2 onwards the "set markup csv" command is supported, and the command was:
printf "set head off\nset feedback off\nset arraysize 5000\nselect field1, field2 from table;" | LD_LIBRARY_PATH=/path/to/oracle12/lib ORACLE_HOME=/path/to/oracle12 /path/to/oracle12/bin/sqlplus -M "CSV ON" -S database
adjust the arraysize variable (5000 is maximum and fastest, but pay attention to the memory), choose the "SET MARKUP CSV {ON|OFF} [DELIMI[TER] character] [QUOTE {ON|OFF}]" parameters and enjoy

How to export half a million records from PL/SQL

I've a table with around 500,000 records. I need all records to be exported in excel. When I query I'm not able to get all as I was said as Out Of memory
Table doesn't have any primary key/Index.
Is there any way to extract?
it would be very easy in to write file output form sqlplus .
mycsv.sql:
SET DEFINE OFF
SET ECHO OFF
SET SERVEROUTPUT OFF
SET TERMOUT OFF
SET VERIFY OFF
SET FEEDBACK OFF
SET PAGESIZE 10000
SET ARRAYSIZE 5000
REM SET HEAD OFF
SET LINE 500
spool /tmp/mycsvfile.csv;
select * from MY_table;
spool off;
exit;
and from Linux prompt you can run like
$> sqlplus username/password #/tmp/mycsv.sql

Fetching SQL execution plan. PL/SQL Developer = strange behaviour. SQL*Plus = no rows selected

I have a problem with fetching SQL plans.
In the final form, I have to fetch them through PL*SQL.
So I have a bash script, a loop to iterate through sql plan names and parameters, and a code like this:
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
CONNECT BLAH/BLAH#BLAH
*CLEAR AND SET COMMANDS HERE*
VARIABLE RC REFCURSOR;
SPOOL ${BERICHT}_${configArray[0]}.DATA
SET TIMING ON;
EXEC :RC := $aktuellesBericht;
SET TIMING OFF;
PRINT RC;
DISCONNECT
QUIT
EOF
And the second part: (logging in as SYS, but without the SYSDBA permissions, I dont have them and I dont think that I will have them...)
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
CONNECT SYSBLAH/SYSBLAH#BLAH
SPOOL ${BERICHT}_${configArray[0]}.SQLPLAN.TXT
CLEAR BREAK
CLEAR COMP
CLEAR COL
select
sqlplan.operation,
sqlplan.options,
sqlplan.object_name,
sqlplan.cost,
sqlplan.depth
from v\$sqlarea sqlarea,
v\$session sesion,
v\$sql_plan sqlplan
where sesion.sql_hash_value = sqlarea.hash_value
and sesion.sql_address = sqlarea.address
and sqlarea.plan_hash_value = sqlplan.plan_hash_value
and sesion.username = 'BLAH' order by sqlplan.depth;
QUIT
EOF
All I can get from this is *.SQLPLAN.TXT files containing just one sentence: no rows selected
What is strange here, that when I do the same in PL/SQL Developer - i get the same results, BUT when I just click on the Auto Refresh timer button on both SQL windows, both queries are running in parallel, and SOMETIMES the second query (the one to fetch SQL plan) is giving me results. And sometimes it doesnt.
It seems that theese commands need to be run in parallel... or am I missing something?
The sql query in my question was never needed.
All I needed is to write to the admin team to grant me the SELECT premissions on:
V$SQL_PLAN, V$SESSION and V$SQL_PLAN_STATISTICS_ALL
The answer to my question was found here.
I will need a deeper understanding of the problem in the future but for now, FWIK, looking deeper into the dbms_xplan package gave me the idea.
The approach to get the queries from the SYSACC account was the wrong idea. This acc has access to all the queries history and it is hard and painful (if even possible) to husk out the sql plan I needed.

Execute plsql dynamiclly via SSH in remote server (using dynamic login info) and get returned value to executing server

I am trying to execute a dynamic plsql command in a remove machine (say 192.168.x.x) and get it's return value to local machine from where I initiate shell script. I am testing two approaches to do this. But none of them seems to work properly.
Approach - I
in this approach if i supply values for ssh and sqlplus (login user/ip and schema user/ip) via shell variable it won't work. working code with hardcoded value is below.
#!/bin/sh
varfld="SYSDATE"
retVal=`echo "SELECT $varfld FROM dual;" | ssh utility#192.168.x.x 'sqlplus -S utility/pwd' | tail -2 | head -1`
echo "return value 1: "$retVal
Approach - II
In this approach I can pass everything i need in a variable. But the plsql command (i.e value of variable $ssh_execute_command) is not recognized inside plsql. Only hardcoded plsql command gets executed.
P.S.This works fine with vsql with few modification to connect Vertica.
v_server_user=utility
v_server_name=192.168.x.x
ssh_v_schema_name=utility
ssh_v_schema_pwd=pwd
varfld="SYSDATE"
execute_command="SELECT $varfld FROM dual;"
retVal=$(ssh $v_server_user#$v_server_name ssh_v_schema_name=$v_schema_name ssh_v_schema_pwd=$v_schema_pwd ssh_execute_command=\""$execute_command"\" 'bash -s' <<SSHSQLTEXT
sqlplus -S $ssh_v_schema_name/$ssh_v_schema_pwd
SET ECHO OFF
SET HEADING OFF
SET FEEDBACK OFF
SELECT SYSDATE FROM dual;
SSHSQLTEXT
)
echo "return value 2: "$retVal
Queries
1. How can we make sql command passed in a variable make work inside pqlplus? or
2. How can we pass required values for ssh and sqlplus (login user/ip and schema user/ip) dynamically and make it work?
The sql statement "SELECT SYSDATE FROM dual;" used here is for testing purpose only. I will be calling package function instead to get return value. And this is yet to be tried in any of these scenarios. If anyone could address that too with example, that would be great!
Thanks in advance.
You need to assign the result of sqlplus to a variable which must be displayed within ssh so that the result is passed to variable retVal. Try the following code:
retVal=$(ssh $v_server_user#$v_server_name ssh_v_schema_name=$v_schema_name ssh_v_schema_pwd=$v_schema_pwd ssh_execute_command=\""$execute_command"\" 'bash -s' <<SSHSQLTEXT
sqlresult=`sqlplus -S $ssh_v_schema_name/$ssh_v_schema_pwd <<EOF
SET ECHO OFF
SET HEADING OFF
SET FEEDBACK OFF
SELECT SYSDATE FROM dual;
exit
EOF`
echo $sqlresult
SSHSQLTEXT
)
echo "return value 2: "$retVal
If you execute the above block of codes, you will have the sysdate as result in $retval

Resources