Oracle PL/SQL в качестве значения для переменной с помощью динамического вызова функции

#sql #oracle #dynamic #plsql #dblink

Вопрос:

У меня есть эта рабочая часть кода, это фрагмент большей рабочей функции. В текущей форме он работает в одном экземпляре «DBLINK», мне нужно изменить его на экземпляр динамического переключения, заменив dblink.

   begin 
      pNDRZ := RW_DOK_SYSTEM.create_header@DBLINK(  aNMGZ => NULL, aNKNT =>     pNKNT    , aREZR =>  'T' , aNTPD =>     pNTPD,     aNODD =>     pNODD    , aOPHP =>     pOPER);
     B2B_P_LOG_ADD(pPAKC => 'B2B_P_DRZ_H_NEW', pERRO => SQLERRM, pTEXT => ' 2.1 Tworz naglowek - OK', pDAKT => SYSDATE, pDBLK => pDBLK, pNRZM => pNRZM, pNDRZ => pNDRZ, pPOZC => pPOZC, pNKNT => pNKNT, pNTWR => pNTWR, pILSP => pILSP, pCNSP => pCNSP, pCBSP => pCBSP, pNPRM => pNPRM, pUWAG => pUWAG, pSTAK => dbms_utility.format_call_stack );
       exception
        when others then
         B2B_P_LOG_ADD(pPAKC => 'B2B_P_DRZ_H_NEW', pERRO => SQLERRM||' - '||SQLStatement2, pTEXT => wynik||' 2.1 Tworz naglowek - ERROR', pDAKT => SYSDATE, pDBLK => pDBLK, pNRZM => pNRZM, pNDRZ => pNDRZ, pPOZC => pPOZC, pNKNT => pNKNT, pNTWR => pNTWR, pILSP => pILSP, pCNSP => pCNSP, pCBSP => pCBSP, pNPRM => pNPRM, pUWAG => pUWAG, pSTAK => dbms_utility.format_call_stack );
      return(0);
  end;
 

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

  pNDRZ := RW_DOK_SYSTEM.create_header@DBLINK(  aNMGZ => NULL, aNKNT =>     pNKNT    , aREZR =>  'T' , aNTPD =>     pNTPD,     aNODD =>     pNODD    , aOPHP =>     pOPER);
 

pNDRZ-это идентификатор uniqe для документа. Мне нужно изменить этот код в динамическую форму, в которой я заменяю ссылку dblink при вызове функции.

Как функция динамического вызова, я могу сделать это с помощью процедуры, но я застрял на этом. Пожалуйста, помогите.

Ответ №1:

Вам понадобится динамический SQL (как вы и предполагали). Для этого

  • создайте локальную переменную, которая будет использоваться для составления инструкции SQL ( l_str в моем примере)
    • почему бы не использовать его напрямую? Поскольку динамический SQL трудно отлаживать, поэтому сначала отобразите его и — как только он будет хорошо работать — выполните его
  • если опубликованный вами код является частью хранимой процедуры, вы, вероятно, передадите имя ссылки на базу данных в качестве параметра. Я создал локальную переменную для этой цели ( l_db_link )

Я сократил те длинные команды, которые вы написали, нет смысла писать их все.

 declare
  l_str      varchar2(200);   -- used to compose a dynamic SQL statement
  l_db_link  varchar2(30) := 'ORCL';
  pndrz      number;          -- just guessing; I don't know its datatype
begin
  l_str := 'select rw_dok_system.create_header@' || l_db_link || '(anmgz => null) from dual';
  execute immediate l_str into pndrz;
  
  b2b_p_log_add(ppakc => 'B2B_P_DRZ_H_NEW');

exception
  ...
end;  
 

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

1. Спасибо, это почти работает, я получаю, что ora-14551 не может выполнить операцию DML внутри запроса. Этот запрос отображает одну строку в таблице документов. Я не могу использовать автономную транзакцию-это рискованно. Я решил использовать каскад операторов else-if. По одному на каждый возможный отдел. И да, я знаю, что это жесткое кодирование «катастрофы в процессе становления» 🙁 Но у меня ограниченное время. Я постараюсь сделать это лучше когда-нибудь в далеком будущем 😉 Спасибо!

2. Пожалуйста. Что касается ошибки, которую вы получили — ну, я не знал, что делает процедура (очевидно, DML). Я рад, что ты знаешь , что происходит и как это исправить.