Oracle:无法在查询错误中执行 DML 操作

Oracle : cannot perform a DML operation inside a query error

我有以下有效的查询,但在其中一部分我想调用此函数 pbweb.adposter.MakeDeepLinkEx 并将值作为 url1 取回,但我收到以下错误:

pbk26w60.GenerateDeepLink 中的 EE:ORA-14551:无法在查询中执行 DML 操作

我有点理解为什么会发生这种情况,因为该函数必须尝试更改 select 内的数据库,这是不允许的。

我知道我需要做类似的事情:

declare
retvar varchar2(500);
begin
    retvar := pbweb.adposter.MakeDeepLinkEx('119686','1368256');
end;

哪个执行但我不知道从这里去哪里?我不太精通 PLSQL,一直在尝试解决这个问题,而写这一切的人正在度假。

有什么方法可以使它达到 return 当前查询中来自 MakeDeepLinkEx 的值,或者无需对其进行太多更改?如果我尝试将开始、结束等添加到查询中,它就会中断。

$sql = "SELECT a.ad_id,
                a.headline, a.pay_period_id,
                (select value from ad_fields where field_id='Jobtitle' and ad_id=a.ad_id) as job_title,
                (select value from ad_fields where field_id='Department' and ad_id=a.ad_id) as department,
                (select value from ad_fields where field_id='Job_Description' and ad_id=a.ad_id) as job_desc,
                (select value from ad_fields where field_id='Champney_Benefits' and ad_id=a.ad_id) as benefits,
                (select value from ad_fields where field_id='Champney_Salary' and ad_id=a.ad_id) as sal_desc,
                a.salary,
                a.salary_max,
              
                (select value from ad_fields where field_id='Location' and ad_id=a.ad_id) as location,
                a.postcode,
                a.email,
                :url || pbweb.pbk00w24.p_encode (
                        null,
                        null,
                        null, 
                        :acc_id , 
                        null, 
                        (select visibility_code from advertisement_visibilities where ad_id = a.ad_id and rownum = 1), 
                        a.ad_id, 
                        null, 
                        null, 
                        null, 
                        null
                ) || CHR(38) AS url,
                pbweb.adposter.MakeDeepLinkEx(a.user_id,a.ad_id) as url1
                from
                advertisements a
                JOIN advertisement_visibilities b ON a.ad_id=b.ad_id
                where a.acc_id = :acc_id AND a.status = 'P' AND start_dt < sysdate AND end_dt >= sysdate and b.visibility_code=:vis";


    $jobs = db_getAll($sql, array(':acc_id' => '202020', ':url' => ADVERT_URL, ':vis' => 'TJP'));

Oracle 非常努力地确保 select 查询是 read-only。如果你想创建一个修改数据的查询,你必须非常努力地工作才能绕过这些保护措施。并愿意忍受一些非常棘手的解决方案。

如果你打算这样做,你绝对必须确定 MakeDeepLinkEx 实际做了什么,并确保让 Oracle 使用优化器认为合适的任何参数调用这个函数(包括行在 where 子句中过滤掉)不会对您的系统造成任何问题。 您要求 Oracle 绕过一些非常重要的护栏,因此由您来确保这条路畅通无阻安全。

您可以创建一个使用自治事务的新函数

create or replace function MakeDeepLinkExAut( p_user_id integer,
                                              p_ad_id   integer )
  return varchar2
as
  l_retvar varchar2(500);
  pragma autonomous_transaction;
begin
  l_retvar := pbweb.adposter.MakeDeepLinkEx(p_user_id, p_ad_id);
  commit;
  return l_retvar;
end;

然后在您的 select 语句中调用这个新函数。