Oracle — скрипт для немедленного завершения сеанса (я получаю ошибку!)

#sql #oracle #plsql

#sql #Oracle #plsql

Вопрос:

Я написал простой скрипт, который немедленно уничтожит сеанс oracle:

 DECLARE
    v_kill VARCHAR2(32767);
BEGIN
    FOR v_kill IN
    (SELECT
            'alter system kill session '''
            ||sid
            ||','
            ||serial#
            ||'''',
            'immediate;'
                    FROM
            v$session
                WHERE
            sql_id='sql_id_here'
    )
    LOOP
        EXECUTE immediate v_kill;
    END LOOP;
END;
  

К сожалению, я получаю сообщение об ошибке, из-за которого я застрял в этой проблеме:

 Error report -
ORA-06550: linia 18, kolumna 21:
PLS-00382: expression is of wrong type
ORA-06550: linia 18, kolumna 3:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
  

Любая помощь будет оценена!

Ответ №1:

Чтобы использовать курсор таким образом, вам нужно присвоить al alias столбцу инструкции и выполнить это:

 BEGIN
    FOR v_kill IN
    (SELECT
            'alter system kill session '''
            ||sid
            ||','
            ||serial#
            || ''' immediate;' as statement
                    FROM
            v$session
                WHERE
            sql_id='sql_id_here'
    )
    LOOP
        dbms_output.put_line (v_kill.statement);
    END LOOP;
END;
  

Кроме того, вам не нужно объявлять переменную для обработки курсора.

Комментарии:

1. Ошибка, скорее всего, сохранится при этом, потому что на самом деле этот запрос возвращает два столбца. Вы присвоили псевдоним второму столбцу (содержит ‘immediate’) в качестве оператора, и это не будет выполняться очень хорошо. Строка ‘immediate’ должна быть объединена с остальной частью команды, чтобы вернуть полную команду в одном столбце.

2. Вы абсолютно правы. Я не заметил ошибки и скопировал ее в своем ответе.

Ответ №2:

Алексей абсолютно прав насчет синтаксиса.

Также имейте в виду, что этот запрос уничтожит сеансы только в текущем экземпляре, если вы запустите это в RAC. Если вам нужно быть абсолютно уверенным, что вы уничтожите все сеансы во всех экземплярах с вашим sql_id, вам нужно использовать gv $ session view и идентификатор сеанса в форме ‘sid, serial #, @inst_id’.

Ответ №3:

 SELECT 'alter system kill session ''' ||sid ||','||serial#  ||',@'||inst_id||''';' from gv$session where sql_id = 'amp;sql_id'