【问题标题】:Oracle - Calling Stored Procedure in a Loop in another Stored ProcedureOracle - 在另一个存储过程中的循环中调用存储过程
【发布时间】:2016-07-25 03:18:01
【问题描述】:

我查看了类似查询的答案,但继续收到另一个错误,似乎无法通过添加创建 proc 的架构来解决。

这是我尝试运行的代码:

create or replace procedure prcReturnDVD
-- define the parameters that this proc will accept
(memberid_in integer, dvd_in integer)
 is
 -- Define local variables
  vNumRem number(2);
BEGIN
-- Update the rental table with the current date
  update rental set rentalreturneddate = current_date where memberid = memberid_in and dvdid = dvd_in;
-- update DVD quantityonhand to reflect the return
  update dvd set dvdquantityonhand = dvdquantityonhand + 1 where dvdid = dvd_in;
-- Check to see how many DVDs are available for rent for this member
  select get_rentalsremaining(memberid_in) into vNumRem from dual;
-- Evaluate the next action depending on number of remaining DVD rentals available
  if vNumRem >= 1 then
  -- need to write a for loop in order to cycle through the DVDs that need to be shipped out
    while vNumRem >= 0 
    loop
      SYSTEM.prcShipNextDVD(memberid_in);
      vNumRem := vNumRem - 1;
    end loop;
  elsif vNumRem = 0 then
  -- message that no rentals are allowed
    dbms_output.put_line('No more rentals allowed.');
  end if;

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    dbms_output.put_line('No Data Returned, process failed.');
  WHEN TOO_MANY_ROWS THEN
    dbms_output.put_line('Too many rows returned into variable, check data and try again.');
  WHEN OTHERS THEN
    dbms_output.put_line('An unidentified error has occured. Please research issue with procedure.');
END;
/

在 LOOP 语句中,我试图调用由同一用户先前编写的另一个过程(我使用 SYSTEM 只是因为它只是一个家庭作业并且它简化了权限):

create or replace procedure prcShipNextDVD
-- define the parameters that this proc will accept
(memberid_in integer)
 is
 -- Define local variables
  vCountOut number(2);
  vAllowedOut number(2);
  vNextDvd number(16);
  vAddedInQueue date;
  vPlaceInQueue number(5);
BEGIN
-- ensure the member is eligible to take out another DVD at this time
-- See how many movies the member currently has out
  select count(*) into vCountOut from rental where memberid = memberid_in and rentalreturneddate is null;
-- See how many movies the member is allowed to have out
  select membershiplimitpermonth into vAllowedOut from membership m, member p where m.membershipid = p.membershipid and p.memberid = memberid_in;
  IF vCountOut < vAllowedOut then
    -- If the number out currently is less than the number allowed out currently
    -- Get next DVD in queue available for shipment
    select get_nextdvd(memberid_in) into vNextDVD, datedaddedinqueue into vAddedInQueue, rentalpriority into vPlaceInQueue from rentalqueue where memberid = memberid_in;
    -- create new record in rental table for this shipment
    insert into rental (rentalid, memberid, dvdid, rentalrequestdate, rentalshippeddate) values (rental_seq.nextval, memberid_in, vNextDVD, vAddedInQueue, current_date);
    -- decrement dvdquantityon hand in dvd table
    update dvd set quantityonhand = quantityonhand - 1 where dvdid = vNextDVD;
    -- remove dvd from queue 
    delete from rentalqueue where memberid = memberid_in and dvdid = vNextDVD ;
    -- manage remaining rentalpriority records by decrementing them properly (like in 2.1)
    update rentalqueue set rentalpriority = rentalpriority - 1 where memberid = memberid_in and rentalpriority >= vPlaceInQueue;
  ELSE
    -- If the member already has the maximum number of movies out at this time
    RAISE_APPLICATION_ERROR(-20101, 'Maximum number of movies out reached. You are not allowed to check out another movie at this time.');
  END IF;

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    dbms_output.put_line('No Data Returned, process failed.');
  WHEN TOO_MANY_ROWS THEN
    dbms_output.put_line('Too many rows returned into variable, check data and try again.');
  WHEN OTHERS THEN
    dbms_output.put_line('An unidentified error has occured. Please research issue with procedure.');
END;
/

即使将架构名称添加到过程调用后,我也会收到以下错误。我也试过用“执行”和“调用”来运行它,但知道它们不能正常工作。

PROCEDURE PRCRETURNDVD compiled 
Errors: check compiler log 
19/7  PL/SQL: Statement ignored 
19/14 PLS-00905: object SYSTEM.PRCSHIPNEXTDVD is invalid

关于我在这方面做错了什么还有其他建议吗?

我正在调用的过程存在问题,但它确实可以编译。

【问题讨论】:

  • Oracle 允许使用不同的参数列表编译相同的过程。因此,您可以存储同一过程的多个“版本”。这称为重载。例如,您可以拥有 myadd(n1 pls_integer, n2 pls_integer) 和 myadd (n1 pls_integer, n2 pls_integer, n3 pls_integer),Oracle 将保留这两个版本的过程。确保您编译的过程没有错误,与您尝试调用的过程具有相同的参数类型。对于故障排除,我会尝试从 SQL 命令行调用一个存储的 proc,而不是从另一个 proc。
  • 我之前有一个我打电话给我的人,但现在……看来我已经把它弄坏了:-/
  • 对..再想想,这可能与有几个版本浮动无关。因为我认为除了在包内之外你不能进行重载。编译后,有一个命令“显示错误”来列出遇到的任何错误。 prcshipnextdvd 的编译返回干净,然后“显示错误”也干净了吗?
  • 点击返回太快...关于为什么这会导致我立即出现错误的任何想法? select count(dvdid) into vCountOut from rental where memberid = memberid_in and rentalreturneddate is null; 错误指向我在哪里进行计数并将其放入我的局部变量之一。我试过 count(*) 和 count(dvdid) 来查看是否是引用不明确的问题。这两个仍然产生以下错误:20/5 PL/SQL: SQL Statement ignored20/70 PL/SQL: ORA-00923: FROM keyword not found where expected
  • 很好,我想我明白了如何在你的例子中继续前进,因为我看到了它给出的实际错误。你的错误在 prcshipnextdvd 的第 20 行。一旦你用多个修复了这个错误进入语句,再次编译并修复错误,直到它干净为止。选择应该是select 1, 2, 3 into var1, var2, var3。写select 1 into var1, 2 into var2, 3 into var3 无效。

标签: oracle stored-procedures


【解决方案1】:

(如 cmets 中所述)

修复 prcShipNextDVD 中的编译错误。

然后来自其他存储过程的调用将起作用。

【讨论】:

  • 浏览并解析 prcShipNextDVD 代码,并准确找到导致问题的部分(从错误告诉我的位置向下大约 2 个语句)。一旦修复,编译没有问题(在其他一些列名被识别为拼写错误并更正后),然后调用 prcShipNextDVD 的后续过程编译没有投诉。感谢您的耐心等待。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-25
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 2018-07-04
相关资源
最近更新 更多