PL / SQL: переменная связывания не существует - PullRequest
4 голосов
/ 16 февраля 2012

Как изменить эту процедуру, чтобы она использовала переменные связывания

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 ]

5 голосов
/ 16 февраля 2012

Переменные связывания в вашем выражении обрабатываются как буквенные строки, а не как заполнители. Если вы выводите оператор, который вы генерируете:

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 в аргументах и ​​в выражении.

0 голосов
/ 16 февраля 2012

Я верю, что это может сработать

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; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...