【问题标题】:ORA-14551: cannot perform a DML operation inside a queryORA-14551: 无法在查询中执行 DML 操作
【发布时间】:2010-07-19 11:27:32
【问题描述】:

我在package 中有以下内容,它给了我一个错误:

ORA-14551: cannot perform a DML operation inside a query

代码是:

DECLARE 
    CURSOR F IS
        SELECT ROLE_ID 
        FROM ROLE 
        WHERE GROUP = 3 
        ORDER BY GROUP ASC;

BEGIN
FOR R IN F LOOP

DELETE FROM my_gtt_1;
COMMIT;

 INSERT INTO my_gtt_1
  ( USER, role, code, status )
(SELECT 
 trim(r.user), r.role, r.code, MAX(status_id)
FROM 
  table1 r, 
  tabl2 c
WHERE 
      r.role = R.role
  AND r.code IS NOT NULL
  AND c.group = 3
  GROUP BY 
  r.user, r.role, r.code);

  SELECT c.role,
                  c.subgroup,
                  c.subgroup_desc,
                  v_meb_cnt
                  INTO record_type
           FROM   ROLE c
           WHERE c.group = '3' and R.role = '19'
           GROUP BY c.role,c.subgroup,c.subgroup_desc;

  PIPE ROW (record_type);



END LOOP;

END;

我在我的一个程序中这样调用包...:

OPEN cv_1 for SELECT * FROM TABLE(my_package.my_func);

我怎样才能避免这个ORA-14551 错误?

仅供参考,我没有将整个代码粘贴到循环中。基本上在循环中,我在 GTT 中输入内容,从 GTT 中删除内容,然后从 GTT 中选择内容并将其附加到光标上。

【问题讨论】:

    标签: oracle plsql temp-tables


    【解决方案1】:

    错误的意思很清楚:如果我们从 SELECT 语句中调用一个函数,它就不能执行 DML 语句,即 INSERT、UPDATE 或 DELETE,或者实际上是 DDL 语句。

    现在,您发布的代码的 sn-p 包含对 PIPE ROW 的调用,因此很明显您将其称为 SELECT * FROM TABLE()。但它包含 DELETE 和 INSERT 语句,显然它违反了 SELECT 语句中函数所需的纯度级别。

    因此,您需要删除那些 DML 语句。您正在使用它们来填充全局临时表,但这是个好消息。您没有包含任何实际使用 GTT 的代码,因此很难确定,但通常不需要使用 GTT。有了更多详细信息,我们可以建议解决方法。

    这与this other question of yours 有关吗?如果是这样,您是否按照我的建议检查that answer I had given to a similar question


    为了完整起见,可以在 SELECT 语句中调用的函数中包含 DML 和 DDL 语句。解决方法是使用 AUTONOMOUS_TRANSACTION pragma。这很少是一个好主意,在这种情况下肯定不会有帮助。因为事务是自治的,所以它所做的更改对调用事务是不可见的。在这种情况下,这意味着该函数无法在 GTT 中看到删除或插入的结果。

    【讨论】:

    • 查看代码及其使用 GTT 的方式,看起来您绝对可以在单个操作中使用插入/选择的结果填充“record_type”。我还会将 'record_type' 称为 'role_record' - 更好地为类型保留 _type。
    【解决方案2】:

    错误意味着您正在从修改数据的函数中进行选择(在您的情况下为删除、插入)。

    如果您需要该功能,请将该功能中的数据修改语句删除到单独的 SP 中。 (我想我从代码 sn-p 中不明白为什么要在循环中删除并插入)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      • 2011-05-04
      • 1970-01-01
      • 2019-11-05
      • 2012-02-02
      • 2013-05-10
      • 2011-11-10
      相关资源
      最近更新 更多