2016-12-29 4 views
0

У меня есть процедура, которая обновляет ~ 700 строк из таблицы на основе определенных дат. Я хочу, если процедура по какой-то причине сработает, чтобы перезапустить процедуру, откуда она ушла, а не от начала (например: перейти к строке214).dynamic goto in oracle plsql

Если я пытаюсь что-то вроде этого:

begin 

goto &label; 

<N1>; 

dbms_output.put_line(1); 

<N2>; 

dbms_output.put_line(2); 

end; 

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

Как я могу сделать что-то подобное без амперсанда (&)? Если я объявляю метку как переменную, она не работает или я не знаю, как заставить ее работать.

+0

Возможно, вы захотите изменить логику. Блоки PL/SQL не предназначены для прямого взаимодействия человека во время выполнения. Ваша процедура должна иметь отдельные «Логические единицы», чтобы ее можно было повторно запустить. –

+0

Создать специальную таблицу для статуса обновления. Вместо lables обертывают логику в операторы if-then, проверяющие статус обновления. Обновление статуса и фиксация после выполнения шага. На следующем этапе будет отображаться обновление состояния и нормально работать. При повторном запуске первые N шагов будут пропущены. Ручное взаимодействие требуется, если что-то совершается неправильно - в этом случае вам необходимо сбросить/изменить статус обновления в вашей таблице. –

+0

Вопрос в том, как вы можете перейти goto динамически, я знаю, что вы можете, но я не знаю, как, проблема в том, как вы можете объявить метку как переменную. – Iulian

ответ

2

Вы не можете выполнить «динамический GOTO» в статическом блоке PL/SQL. Причина в том, что любой аргумент, который следует за ключевым словом GOTO, будет интерпретироваться как метка, на которую вы хотите перейти, а не как выражение, которое будет оценивать метку.

О ближайший вы получите это:

declare 
    l_label VARCHAR2(30) := 'N2'; 
BEGIN 

CASE l_label 
    WHEN 'N1' THEN GOTO N1; 
    WHEN 'N2' THEN GOTO N2; 
    ELSE raise_application_error (-20001, 'Unknown label: ' || l_label); 
END CASE; 

<<N1>> 
    DBMS_OUTPUT.put_line (1); 

<<N2>> 
    DBMS_OUTPUT.put_line (2); 
END; 
+1

Кстати, я не знаю специфики вашего процесса, но для обновляемых 700 строк я бы всерьез рассматривал просто «ROLLBACK» все в случае ошибки, а не беспокоиться о перезапуске. –

+0

Стол представляет собой приборную панель с различной информацией, независимой друг от друга, поэтому я предпочитаю сохранять те, которые я уже вычислил. – Iulian

0

В то время как вы не можете сделать это в статическом PL/SQL, ваше использование амперсанд (&) означает, что вы можете использовать SQL * Plus и просто хотите, чтобы человек не должен был вводить значение метки во время выполнения.

В SQL * Plus вы можете это сделать.

column label_value old_value label; 
set termout off 
REM Replace the following SQL with something that will get the correct label. 
select 'N2' label_value FROM dual; 
set termout on 
set verify off 

set serveroutput on 

begin 
    goto &label; 
    <<N1>> 
    dbms_output.put_line('N1'); 
    <<N2>> 
    dbms_output.put_line('N2'); 
end; 
/
+0

Реальный вопрос: как я могу избавиться от амперсанда (&). – Iulian

+0

'select 'N2' label_value FROM dual' загружает метку, в которую вы хотите перейти, в переменную' & label'. Это не требует взаимодействия с человеком, как вы упомянули в своем вопросе. –

+0

Он не работает (попробовал), чтобы выбрать _value в переменной амперсанда. С label_value он просит меня объявить переменную label_value, только с меткой (объявленной как varchar2) она все еще запрашивает значение. Может быть, это что-то вроде этого, но с другим синтаксисом. – Iulian