如何从 PLSQL Oracle 过程中删除数据或清空游标?

Posted

技术标签:

【中文标题】如何从 PLSQL Oracle 过程中删除数据或清空游标?【英文标题】:How to remove data from or empty a cursor in PLSQL Oracle Procedure? 【发布时间】:2019-11-07 10:38:07 【问题描述】:

我想从表中提取一些行到游标中,在完成我想要的工作之后,我想清空游标以便我可以再次使用游标。整个过程将在一个循环中。我已经搜索了很多次,但我没有得到我想要的帖子。我想我已经明确了自己想要什么。简而言之,我想将我的光标视为 Java 中的 ArrayList。

【问题讨论】:

你检查了documentation,你可以OPENFETCHCLOSEa cursor... 光标一旦生成就不能删除。你需要一个收藏。 在 PL/SQL 中执行循环处理的要求始终是一个琥珀色标志,特别是对于具有 Java 或类似背景的人(没有冒犯)。 SQL 是一种面向集合的范例,PL/SQL 在与集合一起使用时效果最好。因此,您可以提供更多关于您为此光标选择的数据以及您打算如何在此循环中处理它的详细信息。如果您这样做,我们可以帮助您实现最有效的实施。 您好,数据没那么复杂。例如,食品价格表。我有一个查询,例如“从金额 【参考方案1】:

正如其他人所说,您需要将游标提取到集合中(或者不要使用显式游标和 BULK COLLECT 直接与 INTO 一起使用(见下文)。将其包含在集合中后,您可以遍历并删除条目满足某些要求。PL/SQL 集合具有 first 和 next 函数,它们像 Java 中的 Iterator 一样协同工作,因此您可以在循环访问条目时删除条目。

DECLARE

  -- table definition
  TYPE t_obj_tab IS TABLE OF all_objects%ROWTYPE;
  v_obj_tab t_obj_tab;

  -- local variables
  v_index INTEGER;
BEGIN

  -- get some data into a collection
  SELECT *
    BULK COLLECT
    INTO v_obj_tab
    FROM all_objects
   WHERE rownum <= 500;

  -- log the count for demonstration
  dbms_output.put_line(v_obj_tab.count);

  -- get the index of the first element in the collection
  v_index := v_obj_tab.first;

  -- loop through the collection
  WHILE v_index IS NOT NULL
  LOOP

    -- delete objects with some criteria
    IF v_obj_tab(v_index).object_name LIKE '%E%' THEN
      v_obj_tab.delete(v_index);
    END IF;

    -- get next element of collection
    v_index := v_obj_tab.next(v_index);
  END LOOP;

  -- log the count to see if any were deleted
  dbms_output.put_line(v_obj_tab.count);
END;
/
-- 500
-- 206

您应该知道,将大量对象拉入集合中会占用一定比例的内存。 PL/SQL 集合应该尽可能小(我个人喜欢 500 行进行批量处理,但您应该进行基准测试)。建议使用 SQL 过滤结果以仅返回您感兴趣的行(正如其他人也提到的),而不是提取数据并按程序过滤它。

我想您还问如何多次处理同一组数据。如果您想这样做,您可以创建第二个集合变量,将其设置为第一个(创建副本)并将其保留为原始集合。完成处理后,您可以使用它来获取原始行并对它们进行一些不同的处理。

DECLARE

  -- table definition
  TYPE t_obj_tab IS TABLE OF all_objects%ROWTYPE;
  v_obj_tab   t_obj_tab;
  v_obj_tab_2 t_obj_tab;

  -- local variables
  v_index INTEGER;
BEGIN

  -- get some data into a collection
  SELECT *
    BULK COLLECT
    INTO v_obj_tab
    FROM all_objects
   WHERE rownum <= 500;

  -- copy!
  v_obj_tab_2 := v_obj_tab;

  -- log the count for demonstration
  dbms_output.put_line(v_obj_tab.count);

  -- get the index of the first element in the collection
  v_index := v_obj_tab.first;

  -- loop through the collection
  WHILE v_index IS NOT NULL
  LOOP

    -- delete objects with some criteria
    IF v_obj_tab(v_index).object_name LIKE '%E%' THEN
      v_obj_tab.delete(v_index);
    END IF;

    -- get next element of collection
    v_index := v_obj_tab.next(v_index);
  END LOOP;

  -- log the count to see if any were deleted
  dbms_output.put_line(v_obj_tab.count);
  dbms_output.put_line(v_obj_tab_2.count);
END;
/
-- 500
-- 206
-- 500 (copy count)

【讨论】:

以上是关于如何从 PLSQL Oracle 过程中删除数据或清空游标?的主要内容,如果未能解决你的问题,请参考以下文章

plsql导入dmp文件存储过程需要删吗

我如何在 Oracle PLSQL 中解决这个过程(这不是家庭作业或类似的东西)

在作业过程中引用作业编号 - oracle plsql

plsql的odbc如何删除不需要的列

向 Oracle APEX 或 PLSQL 过程发送 POST 请求

在 Oracle 内存缓存中长时间存储 PLSQL 存储过程值