Страница 1 из 1

ORACLE PL/SQL

Добавлено: 27.03.2012 18:45
Гость
оракловский PLSQL отличается таким синтаксисом что читать я это могу а написать чего с нуля - большие трудности.

дано: табличка TABLE1.
колонки:
ID
SQL_STATEMENT

предполагается что в поле SQL_STATEMENT лежит правильный query (каждый query делает что то вроде INSERT... SELECT т.е. заполняет другую табличку)

задание 1
надо написать процедуру на PL SQL которая подряд запускает все TABLE1.SQL_STATEMENT

задание 2
предположим что у каждого SQL_STATEMENT есть 4 параметра (т.е. bind variables или как их там)
у процедуры такие же 4 параметра.
процедура запускает каждый TABLE1.SQL_STATEMENT с 4 параметрами

должно быть просто, но я в этом PLSQL как корова на льду.
а засовывать эти TABLE1.SQL_STATEMENT в код процедуры - плохая идея, их может быть штук 30 и меняться они будут часто.
это что то вроде маленького генератора отчетов

да, правильная обработка ошибок в PLSQL - это как? один из 30 запросов выдал ошибку. куда ее девать, как ее показывать?

Re: ORACLE PL/SQL

Добавлено: 27.03.2012 18:52
Гость
Почему бы не пользоваться хранимыми процедурами с параметрами, которые как раз хранить в записях БД?
Любая книжка Фойерштайна поможет тебе и с обработкой ошибок и с многими другими вещами.

Re: ORACLE PL/SQL

Добавлено: 27.03.2012 19:02
Джимми
EXECUTE IMMEDIATE -http://docs.oracle.com/cd/B12037_01/app ... ems017.htm
цикл плскюель -http://docs.oracle.com/cd/B28359_01/app ... m#CIHEJBAB
правильная обработка - http://docs.oracle.com/cd/B13789_01/app ... 7_errs.htm" onclick="window.open(this.href);return false;
что с ошибкой делать тебе решать.
Ты тестовое задание где-то делаешь что-ли?

Re: ORACLE PL/SQL

Добавлено: 29.03.2012 11:13
JustMax
Надеюсь разберешься сам в рабочем примере.

Код: Выделить всё

CREATE OR REPLACE PROCEDURE PMSD.SP_POSTPROCESSING(v_Profile_Name VARCHAR2, v_Table_To_Export VARCHAR2) IS

  v_Error VARCHAR2(250);
  v_Execute VARCHAR2(1000);
  
BEGIN
   FOR r_Postprocess_Procs IN (SELECT Procedure_Name FROM postprocess_procedure WHERE profile_name = v_Profile_Name ORDER BY invoke_order) LOOP
     v_Execute := 'BEGIN '||r_Postprocess_Procs.Procedure_Name||'(:1); END;';
     EXECUTE IMMEDIATE v_Execute USING v_Table_To_Export;
   END LOOP;  
EXCEPTION
     WHEN OTHERS THEN
       v_Error := SUBSTR(SQLERRM,1,250); 
       INSERT INTO pmsd.protocol (action_date, name, descr) VALUES (SYSDATE, 'Error in export postprocessing', v_Error );
       COMMIT;
       RAISE;
END SP_POSTPROCESSING;
/
Вместо процедур можно также использовать текст SQL запросов с subtitute параметрами :1 :2 :3 и так далее, а потом подставлять их после USING

Re: ORACLE PL/SQL

Добавлено: 29.03.2012 11:55
Гость
JustMax писал(а):Надеюсь разберешься сам в рабочем примере.

Код: Выделить всё

CREATE OR REPLACE PROCEDURE PMSD.SP_POSTPROCESSING(v_Profile_Name VARCHAR2, v_Table_To_Export VARCHAR2) IS

  v_Error VARCHAR2(250);
  v_Execute VARCHAR2(1000);
  
BEGIN
   FOR r_Postprocess_Procs IN (SELECT Procedure_Name FROM postprocess_procedure WHERE profile_name = v_Profile_Name ORDER BY invoke_order) LOOP
     v_Execute := 'BEGIN '||r_Postprocess_Procs.Procedure_Name||'(:1); END;';
     EXECUTE IMMEDIATE v_Execute USING v_Table_To_Export;
   END LOOP;  
EXCEPTION
     WHEN OTHERS THEN
       v_Error := SUBSTR(SQLERRM,1,250); 
       INSERT INTO pmsd.protocol (action_date, name, descr) VALUES (SYSDATE, 'Error in export postprocessing', v_Error );
       COMMIT;
       RAISE;
END SP_POSTPROCESSING;
/
Вместо процедур можно также использовать текст SQL запросов с subtitute параметрами :1 :2 :3 и так далее, а потом подставлять их после USING
Спасибо!!! это точно оно!!!

тока один вопрос
WHEN OTHERS - это типа catch all такое?
а как сделать чтобы любые ошибки выдавались в stdout или лучше в stderr и цикл продолжался (я точно знаю что эта процедура будет запускаться из скрипта у которого есть stdout и stderr)?
ну т.е. нужен try - catch блок вокруг EXECUTE IMMEDIATE основные ошибки будут лезть оттуда

Re: ORACLE PL/SQL

Добавлено: 29.03.2012 13:59
The__Which
вот так делаешь "try catch" на каждую итерацию цикла:

Код: Выделить всё

begin 
  for ,,,, loop
     begin
        execute immediate ...
     exception
         when others...
            обрабатываешь, z.B. пишешь сообщение об исключение об исключении куда тебе надо
     end; 
  end loop;
end;
аналога stdout нет. Есть dbms_output.put_line - он обычно только для отладки. Так как выплевывает он только в Output ДАННОЙ текущей Oracle-сессии да и то если ты это незабыл включить.