I am trying to learn Oracle stored procedures and I cannot make them run properly on SQL Fiddle or DBfiddle. I don't have access to an installed Oracle database.
Here is my code from http://sqlfiddle.com/#!4/e53857/5
CREATE TABLE user_1 (password varchar(10))
/
create procedure updateUsers
( new_p in varchar2)
as
begin
SAVEPOINT before;
update user_1 set password = 'in proc';
dbms_output.put_line(SQL%RowCount);
commit;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error: ' || SQLCODE || ' - ' || SQLERRM);
end;
/
and the query pane
insert into user_1 values ('initial');
select password from user_1;
update user_1 set password = 'from query';
SELECT password from user_1;
exec (updateUsers );
select password from user_1;
When I look at the last output below the update in the query pane has worked, the stored procedure hasn't changed anything, the value of password is still from query and there is no error message.
The line ending in the left pane is / and ; in the right pane.
I would appreciate any help and pointers.
If another online tool is easier to use for Oracle than SQL fiddle I'm open to suggestions.
I've found the solution!
schema pane, line ending / both panes
CREATE TABLE user_1 (password varchar(10))
/
create procedure updateUsers
( new_p in varchar2)
as
begin
SAVEPOINT before;
update user_1 set password = new_p;
dbms_output.put_line(SQL%RowCount);
commit;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error: ' || SQLCODE || ' - ' || SQLERRM);
end;
/
query pane
insert into user_1 values ('initial')/
select password from user_1/
update user_1 set password = 'from query'/
SELECT password from user_1/
begin
updateUsers('new_pass') ;
end;
/
select password from user_1/
output
PASSWORD
initial
PASSWORD
from query
PASSWORD
new_pass
see also extension
http://sqlfiddle.com/#!4/b942cc/3
There is a variable representing a string :
create or replace procedure create_user(login varchar2)
is
begin
execute immediate 'create user "' || login || '" identified by 1 default tablespace tbs_sse';
execute immediate 'grant create session to "' || login || '"';
execute immediate 'grant select any sequence to "' || login || '"';
end;
How to test if the variable login contains special characters other than numbers , letters and # and _ and $ ?
Just you can check using regexp. Create your regexp based on what you are expecting.
SELECT count(1) into counter
FROM dual
WHERE NOT REGEXP_LIKE (LOGIN_VAR , '^[a-zA-Z0-9_$#]+$');
IF (counter != 0) THEN
--Invalid Login alert, error return
END IF;
For more idea about oracle object naming rules please check link
You test - probably - in an IF statement. If so, you can use something like
........
if regexp_like(login, '[^a-zA-Z0-9_#$]')
then ........
........
Since your actual purpose is to check that the name is suitable as an Oracle identifier, you're probably better off using the built-in function dbms_assert.simple_sql_name, e.g.:
dbms_assert.simple_sql_name(login);
execute immediate 'create user "' || login ...
This will raise ORA-44003 string is not a simple SQL name if login has an unsuitable value.
I have a table with users data (email, name, surname, username, password..) and I want to grant each user to see only his own data (like seeing his profile). I have been trying to do it this way:
create or replace
PROCEDURE PR_OWNDATA AS
BEGIN
FOR userRow IN (SELECT COD_USUARIO, USERNAME FROM CAMP.USERS) LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON CAMP.USERS TO "' || userRow.USERNAME || '" WHERE COD_USUARIO = ' || userRow.COD_USUARIO || ';';
END LOOP;
END PR_OWNDATA;
It doesn't work (ORA 06550 "line %s, column %s:\n%s"). But I can't see where is the problem..
I have think about create a VIEW per USER in this way
CREATE VIEW userRow.USERNAME.V_DATOSALUMNO AS SELECT * FROM CAMP.USERS WHERE COD_USUARIO = ' || userRow.COD_USUARIO || ';';
But I don't know if it is the correct way..
Thank you in advance.
I don't understand the name you're giving to the view, but the code should be:
CREATE VIEW my_view_name
AS
SELECT *
FROM CAMP.USERS
WHERE COD_USUARIO = SYS_CONTEXT('USERENV', 'SESSION_USER')
Of course if you're not salting and hashing that password then you're doing it all wrong.
I'm triyin to create a ORACLE USER from my User table inside a procedure. The problem is that I don't know how to call a specific column. I've tried with Camp.user.username and that stuff.
create or replace
PROCEDURE PR_USERPASS AS
BEGIN
UPDATE CAMP.USERS
SET USERNAME = (DBMS_RANDOM.string('x',15)), PASS = DBMS_RANDOM.string('x',12);
EXECUTE IMMEDIATE 'CREATE USER ' || USERNAME || ' IDENTIFIED BY ' || PASSWORD;
EXECUTE IMMEDIATE 'Grant connect to ' || USERNAME;
END PR_USERPASS;
Is there anyway to call that references in the same procedure?
Thank you in advance.
Use a cursor to loop through the Camp.Users table and access its columns. Your code would go something like this (untested):
create or replace
PROCEDURE PR_USERPASS AS
BEGIN
UPDATE CAMP.USERS
SET USERNAME = (DBMS_RANDOM.string('u',15)), PASS = DBMS_RANDOM.string('x',12);
FOR userRow IN (SELECT Username, Pass FROM Camp.Users) LOOP
EXECUTE IMMEDIATE 'CREATE USER ' || userRow.Username || ' IDENTIFIED BY ' || userRow.Pass;
EXECUTE IMMEDIATE 'GRANT CONNECT TO ' || userRow.Username;
END LOOP;
END PR_USERPASS;
Addendum: The original answer generated USERNAME as DBMS_Random.String('x', 15), which allows digits and numbers for the username and password. This caused trouble when the username began with a digit. The answer was changed to use DBMS_Random.String('u', 15) to generate only Oracle-acceptable username values. The password seemed to be OK with the leading digit.
If usernames beginning with a digit are wanted, just surround the username with double quotes:
EXECUTE IMMEDIATE 'CREATE USER "' || userRow.Username || '" IDENTIFIED BY ' || userRow.Pass;
EXECUTE IMMEDIATE 'GRANT CONNECT TO "' || userRow.Username || '"';
That said, I'm not sure if having non-standard usernames is such a good idea.
Documentation for DBMS_Random.String can be found here.
I want to drop some users in Oracle DB using sqlplus but I am getting error:
SQL> DROP USER test CASCADE;
DROP USER test CASCADE
*
ERROR at line 1:
ORA-01940: cannot drop a user that is currently connected
I followed the link in SO to find out the sessions - Dropping a connected user from an Oracle 10g database schema
But when I ran the command I am not getting any results:
SQL> select sid,serial# from v$session where username = 'test';
no rows selected
Please help me how to drop users in this case.
Users are all capitals in v$session (and data dictionary views). If you match with capitals you should find your session to kill.
SELECT s.sid, s.serial#, s.status, p.spid
FROM v$session s, v$process p
WHERE s.username = 'TEST' --<<<--
AND p.addr(+) = s.paddr
/
Pass actual SID and SERIAL# values for user TEST then drop user...:
ALTER SYSTEM KILL SESSION '<SID>, <SERIAL>'
/
Solution :
login as sysdaba:
sqlplus / as sysdba
then:
sql>Shutdown immediate;
sql>startup restrict;
sql>drop user TEST cascade;
If you want to re-activate DB normally either reset the server or :
sql>Shutdown immediate;
sql>startup;
:)
Issue has been fixed using below procedure :
DECLARE
v_user_exists NUMBER;
user_name CONSTANT varchar2(20) := 'SCOTT';
BEGIN
LOOP
FOR c IN (SELECT s.sid, s.serial# FROM v$session s WHERE upper(s.username) = user_name)
LOOP
EXECUTE IMMEDIATE
'alter system kill session ''' || c.sid || ',' || c.serial# || ''' IMMEDIATE';
END LOOP;
BEGIN
EXECUTE IMMEDIATE 'drop user ' || user_name || ' cascade';
EXCEPTION WHEN OTHERS THEN
IF (SQLCODE = -1940) THEN
NULL;
ELSE
RAISE;
END IF;
END;
BEGIN
SELECT COUNT(*) INTO v_user_exists FROM dba_users WHERE username = user_name;
EXIT WHEN v_user_exists = 0;
END;
END LOOP;
END;
/
Do a query:
SELECT * FROM v$session s;
Find your user and do the next query (with appropriate parameters):
ALTER SYSTEM KILL SESSION '<SID>, <SERIAL>';
If you use RAC then you need to use GV$* views instead V$*.
Try to find your session by
select * from gv$session where username = 'test';
and then you can kill the session by
alter system kill session 'sid, serial#, #inst_id' immediate;
This can be as simple as:
SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL> DROP USER test CASCADE;
SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
go to services in administrative tools and select oracleserviceSID and restart it
I was trying to follow the flow described here - but haven't luck to completely kill the session.. Then I fond additional step here:
http://wyding.blogspot.com/2013/08/solution-for-ora-01940-cannot-drop-user.html
What I did:
1. select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v$session where username = '<your_schema>'; - as described below.Out put will be something like this:alter system kill session '22,15' immediate;
2. alter system disconnect session '22,15' IMMEDIATE ; - 22-sid, 15-serial - repeat the command for each returned session from previous command
3. Repeat steps 1-2 while select... not return an empty table
4. Call
drop user...
What was missed - call alter system disconnect session '22,15' IMMEDIATE ; for each of session returned by select 'alter system kill session '..
Sometimes Oracle drop user takes long time to execute. In that case user might be connected to the database. Better you can kill user session and drop the user.
SQL> select 'alter system kill session ''' || sid || ',' || serial# || ''' immediate;' from v$session where username ='&USERNAME';
SQL> DROP USER barbie CASCADE;
I had the same problem, Oracle config in default affects letter register. In exact my Scheme_Name was written all Capital letters. You can see your Scheme_Name on "Other Users" tab, if you are using Oracle S
Basically I believe that killing all sessions should be the solution, but...
I found similar discussion - https://community.oracle.com/thread/1054062 to my problem and that was I had no sessions for that users, but I still received the error. I tried also second the best answer:
sql>Shutdown immediate;
sql>startup restrict;
sql>drop user TEST cascade;
What worked for me at the end was to login as the user, drop all tables manually - select for creating drop statements is
select 'drop table ' || TABLE_NAME || ';' from user_tables;
(Needs to be re-run several times because of references)
I have no idea how is that related, I dropped also functions and sequences (because that was all I had in schema)
When I did that and I logged off, I had several sessions in v$session table and when I killed those I was able to drop user.
My DB was still started in restricted mode (not sure if important or not).
Might help someone else.
BTW: my Oracle version is Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
//'SYS' is username from where you wanted to kill session'
SELECT * FROM DBA_TAB_PRIVS WHERE GRANTEE = 'SYS';
**Step 1:**
CREATE OR REPLACE PROCEDURE sys.kill_session(p_sid NUMBER, p_serial NUMBER)
AS
v_user VARCHAR2(30);
BEGIN
SELECT MAX(username)
INTO v_user
FROM v$session
WHERE sid = p_sid
AND serial# = p_serial;
**Step 2**
create or replace procedure kill_session( p_sid in number, p_serial# in number)
is v_count pls_integer;
BEGIN
select count(*) into v_count
from V$session
where username = 'SYS'
and sid = p_sid
and serial# = p_serial# ;
if ( v_count = 1 )
then
execute immediate '
alter system kill session ''' ||
to_char(p_sid,'999999')||','||
to_char(p_serial#,'999999')||'''';
else
raise_application_error( -20001,
'You do not own session ''' ||
p_sid || ',' || p_serial# ||
'''' );
end if;
END;
/
**Step 3**
grant execute on kill_session to SYS;
**Step 4**
select inst_id, sid, serial#, username, action, program, service_name, con_id from gv$session where username like 'FCM_469';
Check there will be no sessions now
**Step 5**
DROP USER USER_345 CASCADE;
Output:User Dropped
Here's how I "automate" Dropping connected users in Oracle database:
# A shell script to Drop a Database Schema, forcing off any Connected Sessions (for example, before an Import)
# Warning! With great power comes great responsibility.
# It is often advisable to take an Export before Dropping a Schema
if [ "$1" = "" ]
then
echo "Which Schema?"
read schema
else
echo "Are you sure? (y/n)"
read reply
[ ! $reply = y ] && return 1
schema=$1
fi
sqlplus / as sysdba <<EOF
set echo on
alter user $schema account lock;
-- Exterminate all sessions!
begin
for x in ( select sid, serial# from v\$session where username=upper('$schema') )
loop
execute immediate ( 'alter system kill session '''|| x.Sid || ',' || x.Serial# || ''' immediate' );
end loop;
dbms_lock.sleep( seconds => 2 ); -- Prevent ORA-01940: cannot drop a user that is currently connected
end;
/
drop user $schema cascade;
quit
EOF