56

我想使用 sqlplus 删除 Oracle DB 中的一些用户,但出现错误:

SQL> DROP USER test CASCADE;
DROP USER test CASCADE
*
ERROR at line 1:
ORA-01940: cannot drop a user that is currently connected

我按照 SO 中的链接查找会话 - Dropping a connected user from an Oracle 10g database schema

但是当我运行命令时,我没有得到任何结果:

SQL> select sid,serial# from v$session where username = 'test';

no rows selected

请帮助我在这种情况下如何删除用户。

4

13 回答 13

80

用户都是v$session(和数据字典视图)中的大写字母。如果您与大写字母匹配,您应该找到要杀死的会话。

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
 /

为用户 TEST 传递实际 SID 和 SERIAL# 值,然后删除用户...:

ALTER SYSTEM KILL SESSION '<SID>, <SERIAL>'
/
于 2013-03-27T17:40:52.493 回答
41

解决方案 :

以 sysdaba 身份登录:

sqlplus  / as sysdba

然后:

sql>Shutdown immediate;

sql>startup restrict;

sql>drop user TEST cascade;

如果要正常重新激活数据库,请重置服务器或:

sql>Shutdown immediate;

sql>startup;

:)

于 2014-02-11T11:18:50.570 回答
8

问题已使用以下程序修复:

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;
/
于 2018-06-06T03:30:43.557 回答
5

做一个查询:

SELECT * FROM v$session s;

找到您的用户并执行下一个查询(使用适当的参数):

ALTER SYSTEM KILL SESSION '<SID>, <SERIAL>';

于 2014-10-23T13:41:03.190 回答
1

转到管理工具中的服务并选择 oracleserviceSID 并重新启动它

于 2015-08-08T22:12:58.627 回答
1

我试图按照这里描述的流程 - 但没有运气完全终止会话。然后我喜欢这里的额外步骤:
http ://wyding.blogspot.com/2013/08/solution-for-ora-01940 -cannot-drop-user.html

我做了什么:
1. select 'alter system kill session ''' || sid || ',' || serial# || ''';' from v$session where username = '<your_schema>';- 如下所述。
输出将是这样的:
alter system kill session '22,15' immediate;
2. alter system disconnect session '22,15' IMMEDIATE ;- 22-sid, 15-serial - 对从上一个命令返回的每个会话重复该命令
3. 重复步骤 1-2,但select...不返回空表
4. 调用 drop user...

错过了什么 -alter system disconnect session '22,15' IMMEDIATE ;为每个返回的会话调用select 'alter system kill session '..

于 2015-12-02T18:49:54.977 回答
1

如果您使用 RAC,那么您需要使用GV$*视图来代替V$*。尝试通过以下方式找到您的会话

select * from gv$session where username = 'test';

然后你可以通过

alter system kill session 'sid, serial#, @inst_id' immediate;
于 2019-12-19T10:27:07.053 回答
1

这可以很简单:

SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;

SQL> DROP USER test CASCADE;

SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
于 2020-12-01T12:14:32.813 回答
0

我有同样的问题,默认的 Oracle 配置会影响字母寄存器。确切地说,我的 Scheme_Name 全部是大写字母。如果您使用的是 Oracle S,您可以在“其他用户”选项卡上看到您的 Scheme_Name

于 2014-08-15T05:50:17.893 回答
0

基本上我认为杀死所有会话应该是解决方案,但是......

我发现了类似的讨论 - https://community.oracle.com/thread/1054062解决了我的问题,那是我没有针对该用户的会话,但我仍然收到错误消息。我也尝试了第二个最佳答案:

sql>Shutdown immediate;

sql>startup restrict;

sql>drop user TEST cascade;

最后对我有用的是以用户身份登录,手动删除所有表 - 选择创建删除语句是

select 'drop table ' || TABLE_NAME || ';'  from user_tables;

(因引用需要重新运行多次)

我不知道这有什么关系,我还删除了函数和序列(因为这就是我在模式中所拥有的全部)

当我这样做并注销时,我在v$session表中有几个会话,当我杀死这些会话时,我能够删除用户。

我的数据库仍然以受限模式启动(不确定是否重要)。

可能会帮助别人。

顺便说一句:我的 Oracle 版本是Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

于 2017-06-21T13:26:09.530 回答
0

有时Oracle 删除用户需要很长时间才能执行。在这种情况下,用户可能已连接到数据库。更好的是,您可以终止用户会话并删除用户。

SQL> select 'alter system kill session ''' || sid || ',' || serial# || ''' immediate;' from v$session where username ='&USERNAME';

SQL> DROP USER barbie CASCADE;

于 2020-08-21T19:53:17.600 回答
0
//'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
 
于 2021-07-19T04:29:15.023 回答
-1

以下是我在 Oracle 数据库中“自动”删除连接用户的方法:

# 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
于 2016-03-23T16:02:25.490 回答