foreach游标显式和foreach游标隐式有什么区别

What is the difference between foreach cursor explicit and foreach cursor implicit

这里有一个示例,其中我使用显式游标来解决任务。

set serveroutput on
DECLARE
  CURSOR c_1
  IS
    SELECT 
        LNR, LFNDNR, DATUM, STUECK, ANR
    FROM 
        lagerbuchung;
   CURSOR c_2(p_LNR INT)
   IS
    SELECT 
       ORT
    FROM 
        LAGER
    WHERE
      lager.LNR = p_LNR; 
    v_ort varchar(45);
BEGIN
  FOR v_rec IN c_1
  LOOP
    open c_2(v_rec.LNR);
    fetch c_2into v_ort;
    DBMS_OUTPUT.PUT_LINE(': ' || v_rec.LNR || ' : ' || v_rec.LFNDNR ||' : ' || v_rec.DATUM ||' : ' || v_rec.STUECK || ' : ' || v_rec.ANR || ' : ' || v_ort );
    close c_2;
  END LOOP;
END;

所以我的问题是,显式 foreach 游标和隐式 foreach 游标有什么区别?
代码是否相似?哪个更好用?我试图重现代码,但使用隐式 foreach 游标,但没有成功并放弃了。

显式游标应该显式定义并声明为私有SQL区域,而隐式游标只是一个SQL语句,不需要任何人打开,因为已由数据库自行打开和关闭。

对于你的情况,使用这样的代码

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  v_ort varchar(45);
BEGIN
  FOR v_rec IN 
  (
    SELECT l.ort, lb.lnr, lb.lfndnr, lb.datum, lb.stueck, lb.anr
      FROM lager l
      JOIN lagerbuchung lb
     WHERE lb.lnr = l.lnr 
  )  
  LOOP
    DBMS_OUTPUT.PUT_LINE(': ' || v_rec.lnr || ' : ' || v_rec.lfndnr ||
                         ' : ' || v_rec.datum || ' : ' || v_rec.stueck ||
                         ' : ' || v_rec.anr || ' : ' || v_rec.ort);
  END LOOP;
END;

足以将当前游标转换为隐式游标

如果您显式为游标声明一个变量,那么这个cursor is explicit,例如:

declare
  cursor c1 is
    select 1 as n from dual;
begin
  for r in c1 loop
    dbms_output.put_line(r.n);
  end loop;
end;

如果您在代码中内联 sql 查询(在 FOR LOOP or SELECT INTO 中),PLSQL 会生成隐式 (internal/undeclared) 游标,例如:

begin
  for r in (select 1 as n from dual) loop
    dbms_output.put_line(r.n);
  end loop;
end;

what is the difference between foreach cursor explicit and foreach cursor implicit? Is the code similar ? Which one is better to use?

区别在于显式游标需要声明一个变量。您还需要打开、关闭和获取显式游标。因此,隐式游标通常会产生更简洁的代码。

仍然有显式游标的用例(参见 Practical life examples of oracle explicit cursor use):

  • 您需要在同一个 PLSQL 程序中多次重复使用同一个游标。使用显式游标,您可以重用变量而无需重复查询。
  • 您想通过 LIMIT 子句使用批量收集。使用显式游标,可以直接设置限制。

I've tried to reproduce the code but with using foreach cursor implicit, but didn't manage and gave up.

您可以使用隐式游标直接翻译您的代码:

declare
  v_ort varchar(45);
begin
  for v_rec in (SELECT LNR, LFNDNR, DATUM, STUECK, ANR FROM lagerbuchung) loop
    SELECT ORT into v_ort FROM LAGER WHERE lager.LNR = v_rec.LNR;
    DBMS_OUTPUT.PUT_LINE(': ' || v_rec.LNR || ' : ' || v_rec.LFNDNR ||
                         ' : ' || v_rec.DATUM || ' : ' || v_rec.STUECK ||
                         ' : ' || v_rec.ANR || ' : ' || v_ort);
  end loop;
end;

但是 @Barbaros Özhan 已经发布了使用单个查询的更高效的版本。