PL / SQL:绑定变量不存在

时间:2012-02-16 09:25:31

标签: sql oracle plsql

如何修改此过程以使其使用绑定变量

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; 

它给出了:

  

绑定变量不存在

2 个答案:

答案 0 :(得分:5)

语句中的绑定变量被视为文字字符串而不是占位符。如果输出正在生成的语句:

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;
/

...你会看到如下行:

alter system kill session ':1,:2' immediate

':1,:2'被视为静态值而不是两个绑定变量。你不能在动态DDL中使用绑定变量,我不确定这是否适用于alter命令,所以无论如何这可能是不可能的。

实现此目的的最简单方法可能是在游标中生成整个语句:

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;
/

execute被注释掉(我现在不想杀死我的会话)你可以看到它将运行的命令,如:

alter system kill session '58,47157' immediate

你的方法可能仍然存在缺陷,因为它会杀死正在执行该块的会话,并且它可能会也可能不会最后杀死它。我认为这是未定义行为的领域,我真的不想尝试找出发生的事情......我怀疑这是你真正想要的。

编辑:'有缺陷'评论基于使用user,我的匿名区块中的p_user将是执行用户;在你的proc中,它将是参数的用户。使用关键字作为参数名称会让人感到困惑,所以我建议在args和语句中将名称更改为{{1}}。

答案 1 :(得分:-1)

我相信这可能有用

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;