当前位置: 首页 > 面试题库 >

如何从游标中获取,删除,提交

孙帅
2023-03-14
问题内容

我正在尝试从表中删除很多行。我想尝试将要删除的行放入游标中,然后继续对游标的每一行进行获取,删除,提交操作,直到它为空。

在下面的代码中,我们是fetching行,并将其放入TYPE

我如何修改下面的代码以从图片中删除TYPE,而只是简单地fetch,delete,commit对光标本身进行操作即可。

    OPEN bulk_delete_dup;
    LOOP
        FETCH bulk_delete_dup BULK COLLECT INTO arr_inc_del LIMIT c_rows;

        FORALL i IN arr_inc_del.FIRST .. arr_inc_del.LAST
              DELETE FROM UIV_RESPONSE_INCOME 
              WHERE ROWID = arr_inc_del(i);

        COMMIT;
        arr_inc_del.DELETE;
        EXIT WHEN bulk_delete_dup%NOTFOUND;
    END LOOP;
    arr_inc_del.DELETE;
    CLOSE bulk_delete_dup;

问题答案:

为什么要分批提交?那只会减慢您的处理速度。除非有其他会话试图修改要删除的行,否则由于其他原因,这似乎是有问题的,最有效的方法是简单地使用单个DELETE删除数据,即

DELETE FROM uiv_response_income uri
 WHERE EXISTS( 
    SELECT 1
      FROM (<<bulk_delete_dup query>>) bdd
     WHERE bdd.rowid = uri.rowid
  )

当然,根据游标后面的查询的设计方式,可能会有更理想的书写方式。

如果您确实要消除“批量收集”(这会大大减慢该过程),则可以使用“ WHERE CURRENT OF”语法进行“删除”

SQL> create table foo
  2  as
  3  select level col1
  4    from dual
  5  connect by level < 10000;

Table created.

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10    end loop;
 11* end;
SQL> /

PL/SQL procedure successfully completed.

但是请注意,由于必须锁定行(使用FOR UPDATE子句),因此无法在循环中放入提交。进行提交将释放您使用FOR
UPDATE请求的锁,并且您将得到ORA-01002:提取顺序错误

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10      commit;
 11    end loop;
 12* end;
SQL> /
declare
*
ERROR at line 1:
ORA-01002: fetch out of sequence
ORA-06512: at line 7

如果删除锁定并避免使用WHERE CURRENT
OF语法,而是根据从游标中获取的值删除数据,则可能不会收到运行时错误。但是,这仍然是跨提交读取的,这是一种不好的做法,并且从根本上增加了您至少会间歇性地获得ORA-01555:快照太旧的错误的几率。与单个SQL语句或BULK
COLLECT选项相比,它也会非常缓慢。

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where col1 = l_rowtype.col1;
 10      commit;
 11    end loop;
 12* end;
SQL> /

PL/SQL procedure successfully completed.

当然,您还必须确保您的流程可重新启动,以防您处理行的某些子集并在流程终止之前进行一些未知的临时提交。如果DELETE足以导致不再从游标返回该行,则您的过程可能已经重新启动。但是总的来说,如果您尝试将单个操作分解为多个事务,则需要担心。



 类似资料:
  • 如何注释我header.php中的标语? 我正在使用2014年的主题,并试图遵循WordPress codex中的元标签说明。要生成一个描述元标记,它会指示您将描述添加到标语中。但是这个标语显示在我打开网页的每个窗口/选项卡的顶部(以及我的网站名称)。要隐藏标语,WordPress建议“删除或注释掉标头区域的标签”我做这个有困难。我在header.php?中到底要评论什么,我在标题中没有看到任何带

  • 问题内容: 我正在使用JavaMail-1.5将Gmail帐户的IMAP消息附加到Yahoo帐户。我的要求是从邮件中删除用户标志,因为将邮件附加到其他文件夹时会产生错误。我要从消息中删除所有用户标志吗? 下面是获取标志的代码。 请建议如何从我的邮件中删除。 谢谢 问题答案: 我的问题已通过此代码解决- 此代码删除了导致无法将Gmail附加邮件添加到Yahoo的标志。

  • 问题内容: 我正在从Excel文件中解析数据,该文件在某些​​列标题中具有额外的空白。 当我使用来检查结果数据框的列时,我看到: 因此,我无法执行以下操作: 因为它会告诉我找不到列,因为我要求输入“ Month”而不是“ Month”。 那么,我的问题是如何从列标题中去除不需要的空白? 问题答案: 您可以为该方法提供功能。该方法应做您想要的。 注意 :这将返回一个对象,并在屏幕上显示为输出,但是更

  • 问题内容: 假设我使用以下光标获取某人的通话记录: 现在我将如何删除该光标中的第i个项目?这也可能是获取音乐等信息的光标。因此,我必须问-这是否可能?对于某些游标,我可以理解为不允许删除第三方应用程序。 谢谢。 问题答案: 对不起,您不能从光标中删除。 您必须使用ContentResolver或某种SQL调用。

  • 我知道有人问过这个问题,但我想在直接修改数据库中找到答案,但在这种情况下,我想从用户对象中删除密码,这样密码就不会发送到前端,但是不起作用,尽管是一个对象。 任何想法!!我在用猫鼬

  • 有人有更好的主意吗?