Oracle 在函数内执行过程(ORA-14551错误)

Oracle 在函数内执行过程(ORA-14551错误),oracle,function,procedure,dml,Oracle,Function,Procedure,Dml,这个问题与我的有关。 我有一个过程(PROC\u YEARLYACTIVELIST2),它将显示指定年份的所有活动记录。 它将删除以前的tblactivelist yearly2内容,并插入PROC\u yearlyactivelist 2中的结果 我创建了一个函数,它将执行TBLACTIVELISTYEARLY2,从TBLACTIVELISTYEARLY中选择所有记录,并将其放入光标C_IH,然后返回Crystal Report的表。 下面只是代码的一部分: DECLARE CURSO

这个问题与我的有关。

我有一个过程(
PROC\u YEARLYACTIVELIST2
),它将显示指定年份的所有活动记录。
它将删除以前的
tblactivelist yearly2
内容,并插入
PROC\u yearlyactivelist 2中的结果

我创建了一个函数,它将执行
TBLACTIVELISTYEARLY2
,从
TBLACTIVELISTYEARLY
中选择所有记录,并将其放入
光标C_IH
,然后返回Crystal Report的表。

下面只是代码的一部分:

DECLARE CURSOR C_IH IS SELECT * FROM tblActiveListYearly2; ctr INT; i NUMBER; currDeploymentComputer COL_TYPE_DEPLOYMENT_COMPUTER := COL_TYPE_DEPLOYMENT_COMPUTER NULL); R_IH C_IH%ROWTYPE; BEGIN PROC_YEARLYACTIVELIST2(in_year); OPEN C_IH; i := 0; LOOP (....) 并且有一个
ORA-14551
错误

ORA-14551: cannot perform a DML operation inside a query 
ORA-06512: at "NPLS.PROC_YEARLYACTIVELIST2", line 12
ORA-06512: at "NPLS.GETDEPLOYMENT_COMPUTER", line 3
搜索它,发现它是由于与
插入
更新
删除
双重
冲突造成的

在返回表的函数中执行我的过程还有其他方法吗


谢谢

我认为您需要将DML更改和报告部分分开。进行数据更改的过程应在报表函数调用之外调用…

否;出于非常好的原因,您不能在SELECT语句中执行DML

您正在更改数据库中的数据,Oracle需要数据的读取一致性视图,也就是说,它需要知道您选择的内容不会被您选择的内容更改

你所做的听起来非常不必要;您有一个三步流程:

  • 从表中删除一些数据
  • 在该表中插入新数据
  • 从表中选择数据
  • 为什么不简单地选择你需要的数据;会快很多吗?如果您必须预处理数据,那么您可以有一个过程来异步地选择数据

    我对Crystal Reports一无所知,但您也可以在PL/SQL块中执行此操作

    declare
       l_getdeployment my_variable_type;
    begin
       l_getdeployment := GETDEPLOYMENT_COMPUTER('2012');
    end;
    /
    

    这太复杂了。
    由于我希望将记录从表中获取到crystal report,我将选择的内容放入表中。

    现在,我意识到我可以将过程中的逻辑放入函数中,将其放入
    SYS\u REFCURSOR
    ,返回它并使用以下查询调用函数:

    SELECT * FROM TABLE(GETDEPLOYMENT_COMPUTER('2012'));
    

    无论如何,感谢那些回应和帮助我的人。:)

    但是怎么做呢?我可以将我的过程放在crystal报告中,但我猜crystal无法处理oracle查询。所以,我试图创建一个只返回表的函数。嗯,我可以使用流水线或包函数吗?你能给我一个建议吗?谢谢您是否可以尝试另一种方法—而不是更改表数据—只选择您需要的内容?是的,您是对的。我只是忽略DML,使用表格。谢谢你的回复!:)了解自主交易。不太漂亮,但可能是解决你这种情况的唯一办法。谢谢你的回复:)是的,你说得对!我只是选择了我想要的并使用函数返回。并且每年忽略
    tblactivelist2
    。谢谢您的回复!:)
    SELECT * FROM TABLE(GETDEPLOYMENT_COMPUTER('2012'));