CftClub.ru
Клуб специалистов ЦФТ-Банк

Программное создание джобов
На страницу 1, 2, 3, 4  След.
 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle
Предыдущая тема :: Следующая тема  
Автор Сообщение
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеПн Сен 12, 2011 18:06   Программное создание джобов Ответить с цитатой
Полезность: Нет оценки
Киньте плиз примерчик - создать джоб, выполнить, удалить
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеВт Сен 13, 2011 05:34    Ответить с цитатой
Полезность: 1
Код:
declare -- для Oracle младше 10g не использовать dbms_utility.format_error_backtrace

v$info   rtl.debug_rec;

-- Функция запуска задания Oracle немедленно (на самом деле через неск.сек).
function BackRun(p_ex varchar2) return number is
v$job integer;
v$interval varchar2(2000);-- интервал null - т.е. не повторяется
begin
   dbms_job.submit(v$job, p_ex, sysdate, v$interval, false);
   commit;
   return v$job;
end;

begin
   -- Регистрируемся
   dbms_output.put_line(rtl.open);
   -- Именуем монитор канала - для теста
   rtl.set_debug_pipe('test');

   -- Получаем информацию о названии монитора канала
   rtl.get_debug_all(v$info);

   -- запускаем задание
   debug_pipe('номер задания оракла:'||BackRun(
'declare n integer;
begin
   -- Регистрируемся в джобе, чтобы можно было выполнять операции модели данных ЦФТ-Банк
   n := executor.lock_open(''JOB'', job);
   -- устанавливаем имя канала
   rtl.set_debug_pipe('''||v$info.debug_pipe_name||''');
   -- Ломаем джоб, чтобы в случае если сессию кильнут или она сломается, джеб не перезапустился снова
   -- удалять нельзя, иначе к операциям модели данных нельзя будет обратиться - сломаются
   dbms_job.broken(job, true);

   -- Что-то делаем
   rtl.debug_pipe(''я уже работаю!'',0);


   -- самоудаляемся
   begin
      dbms_job.remove(job);
      commit;
   exception when others then
      rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
   end;
   rtl.close;
exception when others then
   begin
      dbms_job.remove(job);
      commit;
   exception when others then
      rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
   end;
   rtl.close;
end;'
),0);
end;
maestro
Профи


Вступление в Клуб: 12.10.2010
СообщениеВт Сен 13, 2011 09:07    Ответить с цитатой
Полезность: Нет оценки
Выполнить поиск по текстам по ключевому слову [TEXT_JOBS]. Найдете массу примеров.
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеВт Сен 13, 2011 09:21    Ответить с цитатой
Полезность: Нет оценки
А, да.
Есть еще Система [SYSTEM] -> Выполнение заданий по расписанию Smile
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеСр Сен 14, 2011 16:11    Ответить с цитатой
Полезность: Нет оценки
по текстам - это по таблице source ?
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеСр Сен 14, 2011 16:14    Ответить с цитатой
Полезность: Нет оценки
Спасибо за приме6рчик, много полезного для меня, но интересует именно PL\Plus
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеСр Сен 14, 2011 16:34    Ответить с цитатой
Полезность: Нет оценки
nataly пишет:
по текстам - это по таблице source ?

ничего реализующего обычный запуск ораклевого джоба не нашла.
ненавижу pl\plus ))
maestro
Профи


Вступление в Клуб: 12.10.2010
СообщениеЧт Сен 15, 2011 09:25    Ответить с цитатой
Полезность: Нет оценки
nataly пишет:
по текстам - это по таблице source ?

А администраторе словаря с галкой "Операций" в блоке "Просматривать тексты"
nataly пишет:

ненавижу pl\plus ))

Зря. А мы его любим Smile


копипаст первого попавшегося примера из дистрибутивной операции WORK_DEPR

[code]procedure startCalcJob(pDoc ref [TMC_DOCUM], pGroup ref [TMC_GRUP], pHDpt ref [DEPART],/*pFinProv boolean,*/ pDateWork date, pJobIds in out rtl.number_table, p_sign_no_in_out in boolean)
is
vJobObj [TEXT_JOBS];
vJobRef ref [TEXT_JOBS];
vErrStr varchar2(4000);
V_LOG_DIR varchar2(300) := [FP_TUNE]::[LIB].get_str_value('EOD_LOG_DIR',0);
begin
vJobObj%id := next_value('SEQ_ID');
vJobObj.[PLPLUS] :=' PRAGMA INCLUDE ([RUNTIME].[MACRO_LIB]);'||LF$
||' declare'||LF$
||' vJob ref [TEXT_JOBS];'||LF$
||' begin'||LF$
||' vJob := '|| vJobObj%id||';'||LF$
||' set_debug_file('''||V_LOG_DIR||to_char(sysdate,'yymmdd')||'_'||replace(pGroup.[CODE], ' ', '_') || '.log'');'||LF$
||' ::[TMC_DOCUM].[WORK_DEPR].startCalcProcess('
||' '||pDoc%id||LF$
||' ,'||pGroup%id||LF$
||' ,'||nvl( to_char( pHDpt%id ), 'null' )||LF$
||' ,'||' to_date('''||to_char(pDateWork, 'dd/mm/yyyy')||''', ''dd/mm/yyyy'')'||LF$
||' ,'||vJobObj%id||LF$
||' ,'''||bool_char(p_sign_no_in_out) || ''''||LF$
||' );'||LF$

--vCode := vCode|| ' commit;' || nl$;
||' exception when others all then '||LF$
||'null;' || LF$
--||' ::[TEXT_JOBS].[APP_LIB].del_job(vJob);' || LF$
--vCode := vCode|| ' commit;' || nl$;
||' end;'||LF$;
------------------------------------------------------------
vJobObj.[NAME] := 'Расчет амортизации по группе ТМЦ с кодом "' || pGroup.[code] || '" для документа '||pDoc%id||' дата обработки '||to_char(pDateWork, 'DD/MM/YY');
vJobObj.[METHOD_CLASS] := 'TMC_DOCUM';
vJobObj.[SHORT_NAME] := 'c_' || rtl.next_value('SEQ_ID');
vJobObj.[FIRST_TIME] := null;
vJobObj.[STATUS] := [TEXT_JOBS]::[EDIT_AUTO].parse_plplus(vJobObj.[PLPLUS], vErrStr, vJobObj.[PLSQL]);
if vJobObj.[STATUS]='PROCESSED' then
vJobObj.[STATUS] := [TEXT_JOBS]::[EDIT_AUTO].parse_plsql(vJobObj.[PLSQL], vErrStr);
else
pragma error('Ошибка генерации исполняемого кода: ' || vErrStr || nl$ || 'Текст plplus: ' || nl$ || vJobObj.[PLPLUS]);
end if;
if vJobObj.[STATUS]!='VALID' then
pragma error('Ошибка генерации исполняемого кода: ' || vErrStr || nl$ || 'Текст pl/sql: ' || nl$ || vJobObj.[PLSQL]);
end if;
vJobObj%id := ::[TEXT_JOBS]%insert(vJobObj, vJobObj%id);
vJobRef := vJobObj%id;
vJobRef.[ADD_JOB];
vJobRef.[SUBMIT_JOB](null, null,null,null);
rules.set_object_rights(::[TEXT_JOBS]%class, vJobObj%id, 'NEW');
commit;
pJobIds(pJobIds.count + 1) := vJobRef%id;
end;[/code]
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеЧт Сен 15, 2011 10:51    Ответить с цитатой
Полезность: 1
nataly пишет:
Спасибо за приме6рчик, много полезного для меня, но интересует именно PL\Plus


Хорошо, на pl/+ первой строчкой напиши
Код:
pragma pl_sql(true);-- включить расширенный синтаксис
-- остальное почти то же самое

-- для Oracle младше 10g не использовать dbms_utility.format_error_backtrace

-- Функция запуска задания Oracle немедленно (на самом деле через неск.сек).
function BackRun(p_ex varchar2) return number is
v$job integer;
v$interval varchar2(2000);-- интервал null - т.е. не повторяется
begin
   dbms_job.submit(v$job, p_ex, sysdate, v$interval, false);
   commit;
   return v$job;
end;

procedure start_job(p_run varchar2) is
begin
   -- Регистрируемся
--   dbms_output.put_line(rtl.open);--регистрация в pl/+ не нужна
   -- Именуем монитор канала - для теста
--   rtl.set_debug_pipe('test');-- тоже не надо, канал уже поименован

   -- Получаем информацию о названии монитора канала
   get_debug_all(v$info);-- убрали название пакета rtl - само появится

   -- запускаем задание
   debug_pipe('номер задания оракла:'||BackRun(
-- а вот здесь все должно быть на pl/sql!!!!!!!
'declare n integer;
begin
   -- Регистрируемся в джобе, чтобы можно было выполнять операции модели данных ЦФТ-Банк
   n := executor.lock_open(''JOB'', job);
   -- устанавливаем имя канала
   rtl.set_debug_pipe('''||v$info.debug_pipe_name||''');
   -- Ломаем джоб, чтобы в случае если сессию кильнут или она сломается, джеб не перезапустился снова
   -- удалять нельзя, иначе к операциям модели данных нельзя будет обратиться - сломаются
   dbms_job.broken(job, true);

   -- Что-то делаем
   rtl.debug_pipe(''я уже работаю!'',0);
'||p_run||'

   -- самоудаляемся
   begin
      dbms_job.remove(job);
      commit;
   exception when others then
      rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
   end;
   rtl.close;
exception when others then
   begin
      dbms_job.remove(job);
      commit;
   exception when others then
      rtl.debug_pipe(dbms_utility.format_error_backtrace,0);
   end;
   rtl.close;
end;'
),0);
end;


Или тебе необходимо, чтобы текст, написанный на pl/+ выполнялся?
В таком случае могу посоветовать функцию PlusEXr:

Код:

function ParsePlPlus(p_text varchar2) return varchar2 is
m_plsql      varchar2(32767);
m_errors   varchar2(32767);
begin
   m_plsql := p_text;

   --   Уж и не знаю, почему эта процедурка так называется...
   --   но она парсит pl/+ -текст, а большего от нее и не надо
   if (method.generate_view(m_plsql, m_errors) > 0) then
      m_plsql := m_errors;
   end if;

   return m_plsql;
end;

function PlusEXr(p_ex varchar2) return varchar2 is
tr varchar2(32767);
v$ret   varchar2(32767);
begin
   tr := '-- begin pl/plus'||LF$
      ||'function ddd return varchar2 is '
      ||'begin '||p_ex||' end;-- end pl/plus'||LF$;

   tr := ParsePlPlus(tr);
   tr := 'declare '||tr||'begin :res:= ddd; end;';

   if rtl.exec_sql_out(tr,'res',v$ret) <> 0 then
      pragma error('Ошибка при выполнении динамического блока в функции PlusEXr');
   end if;
   return v$ret;
end;

...
-- тут вставляем предыдущий пример с корректировкой:

   -- Что-то делаем
   rtl.debug_pipe(''я уже работаю!'',0);
'||PlusEXr(p_run)||'

   -- самоудаляемся



Последний раз редактировалось: Random (Чт Сен 15, 2011 11:08), всего редактировалось 4 раз(а)
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеЧт Сен 15, 2011 10:59    Ответить с цитатой
Полезность: Нет оценки
nataly пишет:
по текстам - это по таблице source ?


Ну вообще-то да, хотя лучше искать с помощью функции поиска из АРМ Администратор словаря данных
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеЧт Сен 15, 2011 11:17    Ответить с цитатой
Полезность: Нет оценки
maestro пишет:
копипаст первого попавшегося примера из дистрибутивной операции WORK_DEPR


Я прошу прощения, но вот тут - создание новой операции, а потом ее запуск:
maestro пишет:

Код:

   vJobObj.[METHOD_CLASS]    := 'TMC_DOCUM';
   vJobObj.[SHORT_NAME]    := 'c_' || rtl.next_value('SEQ_ID');


По-моему, это из пушки по воробьям Smile
Задача гораздо проще.

Тем более, что если такое сделать у себя, ЦФТ за это по голове не погладит. Как говорится, что позволено Зевсу, не позволено остальным. Для прочих смертных есть спец.пакет RUNTIME.PLP_TOOLS - глянь, тоже много интересного.
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеЧт Сен 15, 2011 16:17    Ответить с цитатой
Полезность: Нет оценки
Спасибо! Джобы с божьей... форумской помощью посоздавала и позапускала. И даже нашла как их удалить.
Следующий вопрос, а вот как бы остановить и удалить по проверке из того же или внешнего модуля, например один из нескольких джобов у меня сбойнул, я отловила этот факт по failure и хочу убить и удалить все остальные
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеПт Сен 16, 2011 09:52    Ответить с цитатой
Полезность: Нет оценки
nataly пишет:
Спасибо! Джобы с божьей... форумской помощью посоздавала и позапускала. И даже нашла как их удалить.
Следующий вопрос, а вот как бы остановить и удалить по проверке из того же или внешнего модуля, например один из нескольких джобов у меня сбойнул, я отловила этот факт по failure и хочу убить и удалить все остальные


Лучше не по failures, а по broken
Код:
   select u(count(1)) in user_jobs%rowtype
      where   (u.[job] = p_job   or u.[what] = p_what)   and (u.[broken] = 'Y' or u.[failures] > 4)


Удалить джоб, можно с помощью dbms_job.remove. Остановить (сломать) - dbms_job.broken(true);. А чтобы убить работающую сессию этого джоба, используй
Код:
for (   select x(v.sid:sid, v.serial#:serial) in user_jobs%rowtype, (v$session%rowtype :v)
   where   x.[CLIENT_INFO] = ''||x.[job]) loop
   method.kill_session(x.sid||','||x.serial);
end loop;

В общем, разберешься Smile

Собственно, method.kill_session это вызов процедуры kill_session, вот только вызвать из pl/+-операции процедуру без pl/sql-вставок или execute immediate у меня не получилось
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеПт Сен 16, 2011 15:09    Ответить с цитатой
Полезность: Нет оценки
Посмотрите свежим взглядом, что где проср...не учла Smile
Задача - распаралелливание формирования отчета. Тренируюсь на Депозитном портфеле как самом простом в этом плане
Использую джобы, каждый из которых обрабатывает свой диапазон данных.
В отчетной форме в секции Проверка запускается N джобов, каждый из которых после успешного завершения самоликвидируется
В секции Тело идет проверка состояний джобов, если все успешно выполнились и самоликвидировались, то типа отчет выполнен, радостно выходим. Если попался сбойный по признаку FAILURES>1, то форма выдает ошибку, типа сори, сбойнула, почистите пож уже сформированные неполные данные ручками и удалите умершие и живые джобы.
Это на текущий момент. Хотелось бы: в случае обнаружения сбойнувшего джоба, отчетик тормозит и удаляет и сбойнутый и выполняемый, и ощищает саму таблицу от того, что успело отработать и успешно туда записаться.
А вот на что сориентироваться, в случаях когда
1- сессия убита
2- джоб убит
3- джоб убит из интерфеса
4 - джоб получил ошибку
Рвботает только в последнем случае, как вычислить предыдущие пока не соображу
nataly
Участник со стажем


Вступление в Клуб: 22.07.2011
СообщениеПт Сен 16, 2011 15:12    Ответить с цитатой
Полезность: Нет оценки
т.е. я поубивала нафиг все джобы, а z$system|_job и z#text_job этого не видят, у них типа все работает...
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle Часовой пояс: GMT + 3
На страницу 1, 2, 3, 4  След.
Страница 1 из 4

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru