0

我将运行一个 pl/sql 块来删除表中超过 30 天的所有数据。

条件是这样的:

它将一次删除 200k 数据,在删除 200k 数据后,我必须等待 10-15 秒。该表中有大约 1 亿条记录。我想在自动化脚本中完成整个删除过程。

DECLARE
   CURSOR c6
   IS
      SELECT                                               /*+parallel(a,32)*/
            a.rowid,a.*
        FROM EB_O.CCO_DIR_CONTRS_ES_GG a
       WHERE a.GG_CREATE_DATE < SYSDATE-30
       AND ROWNUM <=200001;

   TYPE contact_point_id_tab IS TABLE OF c6%ROWTYPE
                                   INDEX BY PLS_INTEGER;

   l_contact_point_id_tab   contact_point_id_tab;
BEGIN
   OPEN c6;

   LOOP
      FETCH c6
      BULK COLLECT INTO l_contact_point_id_tab
      LIMIT 10000;

      EXIT WHEN l_contact_point_id_tab.COUNT = 0;

      IF l_contact_point_id_tab.COUNT > 0
      THEN
         FORALL i
             IN l_contact_point_id_tab.FIRST .. l_contact_point_id_tab.LAST
            DELETE FROM  EB_O.CCO_DIR_CONTRS_ES_GG
                            WHERE rowid =l_contact_point_id_tab (i).rowid;

         COMMIT;
      END IF;

      l_contact_point_id_tab.delete;
   END LOOP;
END;

这是我写的上面的plsql块。如何在多个循环中执行此操作,并且在每个循环之后将有 10-15 秒的等待期,并且对于下一个 200k 数据将再次进行删除操作。循环将继续,直到所有数据都被删除。

注意:对于等待期,DBMS_LOCK.sleep 没有授权

4

2 回答 2

0

我不会通过循环游标来做到这一点。相反,我会做类似的事情:

begin
  loop
    delete FROM EB_O.CCO_DIR_CONTRS_ES_GG
    WHERE GG_CREATE_DATE < SYSDATE-30
    AND ROWNUM <=200000;

    exit when sql%rowcount = 0;

    commit;

    dbms_lock.sleep(10);
  end loop;
end;
/

这样,您可以避免潜在的快照太旧错误(因为您已经提交了游标提取循环),并且您不再将信息提取到内存中以传回数据库,从而提高效率。

于 2019-04-26T08:06:06.917 回答
0

如果您没有访问睡眠功能,只需创建自己的。将以下查询的输出存储在变量中,创建一个循环,当 sysdate 等于存储在变量中的值时退出。

select sysdate+(10 / (24*60*60)) from dual;

此外,您可以将秒数作为输入变量并在查询中传递相同的值,而不是硬编码 10。

于 2019-06-27T12:02:31.893 回答