Reputation: 1499
How to modify this procedure to let it use bind variables
PROCEDURE KILL(user IN VARCHAR2) AS
BEGIN
FOR REC IN (SELECT sid,serial# serial FROM V$SESSION WHERE username = user)
LOOP
execute immediate 'alter system kill session '' :1 , :2 '' immediate'
using rec.sid, rec.serial;
END LOOP;
END;
It gives:
bind variable does not exist
Upvotes: 4
Views: 10724
Reputation: 191245
The bind variables in your statement are being treated as literal strings rather than place holders. If you output the statement you're generating:
BEGIN
FOR REC IN (SELECT sid,serial# serial FROM V$SESSION WHERE username = user)
LOOP
dbms_output.put_line('alter system kill session '':1,:2'' immediate');
END LOOP;
END;
/
... you see lines like:
alter system kill session ':1,:2' immediate
The ':1,:2'
is treated as a static value and not as two bind variables. You can't use bind variables in dynamic DDL, and I'm not sure if that applies to alter
commands, so this may be impossible anyway.
The simplest way to achieve this may be to generate the whole statement in the cursor:
BEGIN
FOR REC IN (
SELECT 'alter system kill session ''' || sid ||','|| serial#
||''' immediate' stmt
FROM V$SESSION WHERE username = user)
LOOP
dbms_output.put_line(rec.stmt);
--execute immediate rec.stmt;
END LOOP;
END;
/
With the execute
commented out (I don't really want to kill my sessions just now) you can just see the commands it will run, like:
alter system kill session '58,47157' immediate
Your approach may still be flawed though as it will kill the session that is executing the block, and it may or may not kill it last. I think this is in the realms of undefined behaviour, and I don't really want to try it to find out what happens... I doubt that's what you actually want anyway.
Edit: 'flawed' comment was based on using user
, which in my anonymous block would be the executing user; in your proc it would be the user from the parameter. Using a keyword as a parameter name is confusing though, so I'd recommend changing the name to something like p_user
, in the args and the statement.
Upvotes: 5
Reputation: 10186
I believe this might work
PROCEDURE KILL(user IN VARCHAR2) AS
BEGIN
FOR REC IN (SELECT sid,serial# serial FROM V$SESSION WHERE username = user)
LOOP
execute immediate 'alter system kill session :1 '||','|| ':2 immediate'
using rec.sid, rec.serial;
END LOOP;
END;
Upvotes: -1