Change passwords of many schemas under different databases without DBA privileges? - oracle

We have many schemas under different databases. I do not have DBA privileges. I do have privileges to log-on to schemas and to change password. We do this password change ones in six months. Currently it's a manual and time consuming process. i.e. log-on to every schema under database/s and change password using "password" command. When I do password changes I have two files - current password and new password.
I log-on to each schema#database and issue following command –
alter user schema_name identified by new_password replace old_password;
Remember I don’t have DBA privileges; I can only log-on to schemas using username and password.
I thought about creating shell script and using “expect” from shell script. Though first trying to find out whether there is any easier approach. I am wondering is there a simple way of doing this either from SQL*Plus or from PL/SQL?

It seems impossible to do it using PLSQL or SQL*Plus because using both of them, you can execute from a single schema only and since there is no DBA privilege, you cannot do it for all schemas, rather you will end up running script after logging into each schema.
You can write a shell script that reads the two files and for each line, it inserts following data into the third file,
sqlplus -s username_1/old_password_1#oracle_instance <<EOF
alter user username_1 identified by new_password1 replace old_password_1;
exit
EOF
sqlplus -s username_2/old_password_2#oracle_instance <<EOF
alter user username_2 identified by new_password_2 replace old_password_2;
exit
EOF
.
.
.
sqlplus -s username_n/old_password_n#oracle_instance <<EOF
alter user username_n identified by new_password_n replace old_password_n;
exit
EOF
and so on
Once the third file is created, execute it after setting its permission to _rwxrwxrwx

You need to script this.
Input: List of tnsalias, List of (schema_name, old password, new password).
Here is the script I use when I alter my account on multiple databases.
$ cat alterpassword.py
"""Update oracle database passwords for user by typing the old and new password once.
"""
import cx_Oracle
import getpass
username = 'bjarte'
connect_strings = ['DB1.SUPERSITE.COM',
'DB2.SUPERSITE.COM',
'DB3.SUPERSITE.COM',
'DB4.SUPERSITE.COM',
'DB5.SUPERSITE.COM',
'DB6.SUPERSITE.COM']
def alter_password(username, old_password, new_password, tnsalias):
connect_string = "%s/%s#%s" % (username, old_password, tnsalias)
try:
connection = cx_Oracle.connect(connect_string)
try:
cursor = connection.cursor()
statement = "alter user %s identified by %s" % (username, new_password)
cursor.execute(statement)
return True
except:
return False
else:
cursor.close()
except:
return False
else:
connection.close()
if __name__ == '__main__':
print "Type in old password"
old_password = getpass.getpass()
print "Type in new password"
new_password = getpass.getpass()
for tnsalias in connect_strings:
success = alter_password(username, old_password, new_password, tnsalias)
if success:
print "password altered for user %s in database %s" % (username, tnsalias)
else:
print "password alternation failed for user %s in database %s" % (username, tnsalias)
You can adjust this script to read input from file and rewrite it in your favorite scripting language - bash, php, Perl, python, ruby or Powershell.
Side note: Schema accounts are not application login-accounts
schema accounts should always be locked (no need for a password change).
When you request for ddl changes for a specific schema, the DBA can open up and give you a password. When done, lock the schema account again.
schema-accounts are special. They own objects and can do ddl like: "drop objecttype objectname". You most likely don't want your applications to have these powerful privileges.

Related

SQLPLUS connection to different dbs

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.

Attempting to connect to an oracle database from shell script

I am trying to connect to an oracle database from a shell script ( I am a new user ) . The script will then pass a query and transfer the result to a variable called canadacount. I have written the code but it does not work
#this script will attempt to connect to a remote database CFQ143 with user ID 'userid' and password 'password'.
#After loggin in it will read data from the PLATFORMSPECIFIC table.
#We can pass a query 'select count (platform) from platformspecific where platform='CANADA';
#The result from this query will be passed to a variable called canadacount which we can then echo back to the user.
canadacount='$ORACLE_HOME/bin/sqlplus -s /nolog<<EOF
connect userid/passsword#CFQ143:1521:CFQ143
set pages 0 feed off
select count (platform) from platformspecific where platform='CANADA';
exit
EOF'
echo $canadacount
The answer is :
I changed the connect line to the following:
connect userid/passsword#CFQ143

Running oracle commands script file from java application

I have an application which has an oracle database, so the installation of the application needs running some oracle commands script files to create the database and perform some DDL operations. Those operations include some table space creation, schema definition etc.
I was trying to prepare an installation wizard using java application. This wizard needs to run these commands. My specific question is: How to run oracle commands script files from inside my java application? I exactly need a java function that takes the sql commands file path as input parameter and executes the commands within the script files from java taking into the eye of consideration that some parameters (e.g. some user-selected names)must be passed to the script file which to be executed
I used to use PL/SQL command line functionality to execute the sql commands as a privileged user.
Here is a section of the file as an example
ACCEPT TS_NAME CHAR PROMPT 'Enter Table Space Name : '
ACCEPT DB_DATAFILE CHAR PROMPT 'Enter DataBase File full path : '
ACCEPT DB_SIZE NUMBER PROMPT 'Enter DataBase File Size (MB) : '
ACCEPT DB_USER CHAR PROMPT 'Enter User Name : '
ACCEPT DB_PASS CHAR PROMPT 'Enter Table Password Name: ' HIDE
ACCEPT DB_TNSNAME CHAR PROMPT 'Enter DATABASE TNSNAME:'
ACCEPT DB_LOG_PATH CHAR PROMPT 'Enter Log File Path : '
PROMPT Create Tablespace
pause Press Return to continue ...
CREATE TABLESPACE &TS_NAME DATAFILE '&DB_DATAFILE' SIZE &DB_SIZE M
AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED LOGGING PERMANENT
EXTENT MANAGEMENT LOCAL AUTOALLOCATE BLOCKSIZE 8K SEGMENT SPACE MANAGEMENT MANUAL;
PROMPT Create User
pause Press Return to continue ...
CREATE USER &DB_USER IDENTIFIED BY &DB_PASS DEFAULT TABLESPACE &TS_NAME PROFILE DEFAULT
QUOTA UNLIMITED ON USERS;
COMMIT;
GRANT CONNECT TO &DB_USER;
GRANT RESOURCE TO &DB_USER;
COMMIT;
I would first correct something from your question, the snippet is not PL/SQL but client-side extension by sqlplus and also you are doing a mistake "committing" after a DDL, you don't need to do that as DDL are not part of a transaction.
The best here I think is converting to actual PL/SQL, say a procedure:
create procedure create_user(ts_name in varchar, db_datafile in varchar, db_size in varchar, db_user in varchar,
db_pass in varchar, db_tnsname in varchar, db_log_path in varchar)
is
begin
execute immediate 'CREATE TABLESPACE '||TS_NAME||' DATAFILE '|| db_datafile ||' SIZE ' ||db_size||'M'||
'AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED LOGGING PERMANENT '||
'EXTENT MANAGEMENT LOCAL AUTOALLOCATE BLOCKSIZE 8K SEGMENT SPACE MANAGEMENT MANUAL';
execute immediate 'CREATE USER '||DB_USER||' IDENTIFIED BY '||DB_PASS||' DEFAULT TABLESPACE '||TS_NAME||' PROFILE DEFAULT QUOTA UNLIMITED ON USERS';
execute immediate 'grant connect, resource to '||db_user;
end;
/
and then from java just recall the procedure with the appropriate parameters, of course you should check the result of all the statements, mine is just an example and needs to be tested and completed with error checks.

How to import an Oracle database from dmp file and log file?

How would I go about creating a database from a dump file? I do not have an existing database with the same structure on my system so it has to be complete with jobs, events, tables, and so on.
I placed the dump and log file in E: drive
I have tried the import utility
E:/>impdp system/tiger#oratest FILE=WB_PROD_FULL_20MAY11.dmp
But I'm getting error as
invalid argument value
bad dump file specification
unable to open dump file "E:\app\admin\oratest\dpdump\WB_PROD_F
ULL_20MAY11.dmp" for read
unable to open file
unable to open file
(OS 2) The system cannot find the file specified.
And when I see in Windows Explorer DMP file(taken from Linux server) is showing as Crash dump file
I don't understand how I can resolve this issue. Please help me to solve this issue.
I'm a complete newbie on Oracle...
How was the database exported?
If it was exported using exp and a full schema was exported, then
Create the user:
create user <username> identified by <password> default tablespace <tablespacename> quota unlimited on <tablespacename>;
Grant the rights:
grant connect, create session, imp_full_database to <username>;
Start the import with imp:
imp <username>/<password>#<hostname> file=<filename>.dmp log=<filename>.log full=y;
If it was exported using expdp, then start the import with impdp:
impdp <username>/<password> directory=<directoryname> dumpfile=<filename>.dmp logfile=<filename>.log full=y;
Looking at the error log, it seems you have not specified the directory, so Oracle tries to find the dmp file in the default directory (i.e., E:\app\Vensi\admin\oratest\dpdump\).
Either move the export file to the above path or create a directory object to pointing to the path where the dmp file is present and pass the object name to the impdp command above.
All this peace of code put into *.bat file and run all at once:
My code for creating user in oracle. crate_drop_user.sql file
drop user "USER" cascade;
DROP TABLESPACE "USER";
CREATE TABLESPACE USER DATAFILE 'D:\ORA_DATA\ORA10\USER.ORA' SIZE 10M REUSE
AUTOEXTEND
ON NEXT 5M EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO
/
CREATE TEMPORARY TABLESPACE "USER_TEMP" TEMPFILE
'D:\ORA_DATA\ORA10\USER_TEMP.ORA' SIZE 10M REUSE AUTOEXTEND
ON NEXT 5M EXTENT MANAGEMENT LOCAL
UNIFORM SIZE 1M
/
CREATE USER "USER" PROFILE "DEFAULT"
IDENTIFIED BY "user_password" DEFAULT TABLESPACE "USER"
TEMPORARY TABLESPACE "USER_TEMP"
/
alter user USER quota unlimited on "USER";
GRANT CREATE PROCEDURE TO "USER";
GRANT CREATE PUBLIC SYNONYM TO "USER";
GRANT CREATE SEQUENCE TO "USER";
GRANT CREATE SNAPSHOT TO "USER";
GRANT CREATE SYNONYM TO "USER";
GRANT CREATE TABLE TO "USER";
GRANT CREATE TRIGGER TO "USER";
GRANT CREATE VIEW TO "USER";
GRANT "CONNECT" TO "USER";
GRANT SELECT ANY DICTIONARY to "USER";
GRANT CREATE TYPE TO "USER";
create file import.bat and put this lines in it:
SQLPLUS SYSTEM/systempassword#ORA_alias #"crate_drop_user.SQL"
IMP SYSTEM/systempassword#ORA_alias FILE=user.DMP FROMUSER=user TOUSER=user GRANTS=Y log =user.log
Be carefull if you will import from one user to another. For example if you have user named user1 and you will import to user2 you may lost all grants , so you have to recreate it.
Good luck, Ivan
If you are using impdp command example from #sathyajith-bhat response:
impdp <username>/<password> directory=<directoryname> dumpfile=<filename>.dmp logfile=<filename>.log full=y;
you will need to use mandatory parameter directory and create and grant it as:
CREATE OR REPLACE DIRECTORY DMP_DIR AS 'c:\Users\USER\Downloads';
GRANT READ, WRITE ON DIRECTORY DMP_DIR TO {USER};
or use one of defined:
select * from DBA_DIRECTORIES;
My ORACLE Express 11g R2 has default named DATA_PUMP_DIR (located at {inst_dir}\app\oracle/admin/xe/dpdump/) you sill need to grant it for your user.

Howto import an oracle dump in an different tablespace

I want to import an oracle dump into a different tablespace.
I have a tablespace A used by User A. I've revoked DBA on this user and given him the grants connect and resource. Then I've dumped everything with the command
exp a/*** owner=a file=oracledump.DMP log=log.log compress=y
Now I want to import the dump into the tablespace B used by User B. So I've given him the grants on connect and resource (no DBA). Then I've executed the following import:
imp b/*** file=oracledump.DMP log=import.log fromuser=a touser=b
The result is a log with lots of errors:
IMP-00017: following statement failed with ORACLE error 20001: "BEGIN DBMS_STATS.SET_TABLE_STATS
IMP-00003: ORACLE error 20001 encountered
ORA-20001: Invalid or inconsistent input values
After that, I've tried the same import command but with the option statistics=none. This resulted in the following errors:
ORA-00959: tablespace 'A_TBLSPACE' does not exist
How should this be done?
Note: a lot of columns are of type CLOB. It looks like the problems have something to do with that.
Note2: The oracle versions are a mixture of 9.2, 10.1, and 10.1 XE. But I don't think it has to do with versions.
You've got a couple of issues here.
Firstly, the different versions of Oracle you're using is the reason for the table statistics error - I had the same issue when some of our Oracle 10g Databases got upgraded to Release 2, and some were still on Release 1 and I was swapping .DMP files between them.
The solution that worked for me was to use the same version of exp and imp tools to do the exporting and importing on the different Database instances. This was easiest to do by using the same PC (or Oracle Server) to issue all of the exporting and importing commands.
Secondly, I suspect you're getting the ORA-00959: tablespace 'A_TBLSPACE' does not exist because you're trying to import a .DMP file from a full-blown Oracle Database into the 10g Express Edition (XE) Database, which, by default, creates a single, predefined tablespace called USERS for you.
If that's the case, then you'll need to do the following..
With your .DMP file, create a SQL file containing the structure (Tables):
imp <xe_username>/<password>#XE file=<filename.dmp> indexfile=index.sql full=y
Open the indexfile (index.sql) in a text editor that can do find and replace over an entire file, and issue the following find and replace statements IN ORDER (ignore the single quotes.. '):
Find: 'REM<space>' Replace: <nothing>
Find: '"<source_tablespace>"' Replace: '"USERS"'
Find: '...' Replace: 'REM ...'
Find: 'CONNECT' Replace: 'REM CONNECT'
Save the indexfile, then run it against your Oracle Express Edition account (I find it's best to create a new, blank XE user account - or drop and recreate if I'm refreshing):
sqlplus <xe_username>/<password>#XE #index.sql
Finally run the same .DMP file you created the indexfile with against the same account to import the data, stored procedures, views etc:
imp <xe_username>/<password>#XE file=<filename.dmp> fromuser=<original_username> touser=<xe_username> ignore=y
You may get pages of Oracle errors when trying to create certain objects such as Database Jobs as Oracle will try to use the same Database Identifier, which will most likely fail as you're on a different Database.
If you're using Oracle 10g and datapump, you can use the REMAP_TABLESPACE clause. example:
REMAP_TABLESPACE=A_TBLSPACE:NEW_TABLESPACE_GOES_HERE
For me this work ok (Oracle Database 10g Express Edition Release 10.2.0.1.0):
impdp B/B full=Y dumpfile=DUMP.dmp REMAP_TABLESPACE=OLD_TABLESPACE:USERS
But for new restore you need new tablespace
P.S. Maybe useful http://www.oracle-base.com/articles/10g/OracleDataPump10g.php
What version of Oracle are you using? If its 10g or greater, you should look at using Data Pump instead of import/export anyway. I'm not 100% sure if it can handle this scenario, but I would expect it could.
Data Pump is the replacement for exp/imp for 10g and above. It works very similar to exp/imp, except its (supposedly, I don't use it since I'm stuck in 9i land) better.
Here is the Data Pump docs
The problem has to do with the CLOB columns. It seems that the imp tool cannot rewrite the create statement to use another tablespace.
Source: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:66890284723848
The solution is:
Create the schema by hand in the correct tablespace. If you do not have a script to create the schema, you can create it by using the indexfile= of the imp tool.
You do have to disable all constraints your self, the oracle imp tool will not disable them.
After that you can import the data with the following command:
imp b/*** file=oracledump.dmp log=import.log fromuser=a touser=b statistics=none ignore=y
Note: I still needed the statistics=none due to other errors.
extra info about the data pump
As of Oracle 10 the import/export is improved: the data pump tool ([http://www.oracle-base.com/articles/10g/OracleDataPump10g.php][1])
Using this to re-import the data into a new tablespace:
First create a directory for the temporary dump:
CREATE OR REPLACE DIRECTORY tempdump AS '/temp/tempdump/';
GRANT READ, WRITE ON DIRECTORY tempdump TO a;
Export:
expdp a/* schemas=a directory=tempdump dumpfile=adump.dmp logfile=adump.log
Import:
impdp b/* directory=tempdump dumpfile=adump.dmp logfile=bdump.log REMAP_SCHEMA=a:b
Note: the dump files are stored and read from the server disk, not from the local (client) disk
my solution is to use GSAR utility to replace tablespace name in the DUMP file. When you do replce, make sure that the size of the dump file unchanged by adding spaces.
E.g.
gsar -f -s"TSDAT_OV101" -r"USERS " rm_schema.dump rm_schema.n.dump
gsar -f -s"TABLESPACE """USERS """ ENABLE STORAGE IN ROW CHUNK 8192 RETENTION" -r" " rm_schema.n1.dump rm_schema.n.dump
gsar -f -s"TABLESPACE """USERS """ LOGGING" -r" " rm_schema.n1.dump rm_schema.n.dump
gsar -f -s"TABLESPACE """USERS """ " -r" " rm_schema.n.dump rm_schema.n1.dump
I wanna improve for two users both in different tablespaces on different servers (databases)
1.
First create a directories for the temporary dump for both servers (databases):
server #1:
CREATE OR REPLACE DIRECTORY tempdump AS '/temp/old_datapump/';
GRANT READ, WRITE ON DIRECTORY tempdump TO old_user;
server #2:
CREATE OR REPLACE DIRECTORY tempdump AS '/temp/new_datapump/';
GRANT READ, WRITE ON DIRECTORY tempdump TO new_user;
2.
Export (server #1):
expdp tables=old_user.table directory=tempdump dumpfile=adump.dmp logfile=adump.log
3.
Import (server #2):
impdp directory=tempdump dumpfile=adump_table.dmp logfile=bdump_table.log
REMAP_TABLESPACE=old_tablespace:new_tablespace REMAP_SCHEMA=old_user:new_user
The answer is difficult, but doable:
Situation is: user A and tablespace X
import your dump file into a different database (this is only necessary if you need to keep a copy of the original one)
rename tablespace
alter tablespace X rename to Y
create a directory for the expdp command en grant rights
create a dump with expdp
remove the old user and old tablespace (Y)
create the new tablespace (Y)
create the new user (with a new name) - in this case B - and grant rights (also to the directory created with step 3)
import the dump with impdp
impdp B/B directory=DIR dumpfile=DUMPFILE.dmp logfile=LOGFILE.log REMAP_SCHEMA=A:B
and that's it...
Because I wanted to import (to Oracle 12.1|2) a dump that was exported from a local development database (18c xe), and I knew that all my target databases will have an accessible tablespace called DATABASE_TABLESPACE, I just created my schema/user to use a new tablespace of that name instead of the default USERS (to which I have no access on the target databases):
-- don't care about the details
CREATE TABLESPACE DATABASE_TABLESPACE
DATAFILE 'DATABASE_TABLESPACE.dat'
SIZE 10M
REUSE
AUTOEXTEND ON NEXT 10M MAXSIZE 200M;
ALTER DATABASE DEFAULT TABLESPACE DATABASE_TABLESPACE;
CREATE USER username
IDENTIFIED BY userpassword
CONTAINER=all;
GRANT create session TO username;
GRANT create table TO username;
GRANT create view TO username;
GRANT create any trigger TO username;
GRANT create any procedure TO username;
GRANT create sequence TO username;
GRANT create synonym TO username;
GRANT create synonym TO username;
GRANT UNLIMITED TABLESPACE TO username;
An exp created from this makes imp happy on my target.
---Create new tablespace:
CREATE TABLESPACE TABLESPACENAME DATAFILE
'D:\ORACL\ORADATA\XE\TABLESPACEFILENAME.DBF' SIZE 350M AUTOEXTEND ON NEXT 2500M MAXSIZE UNLIMITED
LOGGING
PERMANENT
EXTENT MANAGEMENT LOCAL AUTOALLOCATE
BLOCKSIZE 8K
SEGMENT SPACE MANAGEMENT MANUAL
FLASHBACK ON;
---and then import with below command
CREATE USER BVUSER IDENTIFIED BY VALUES 'bvuser' DEFAULT TABLESPACE TABLESPACENAME
-- where D:\ORACL is path of oracle installation

Resources