调用封装成过程,Oracle PL/SQL

Posted

技术标签:

【中文标题】调用封装成过程,Oracle PL/SQL【英文标题】:Call package into a procedure, Oracle PL/SQL 【发布时间】:2016-03-07 13:18:15 【问题描述】:

我正在尝试找出我们应该在 Oracle 的 11g PL/SQL 中解决的这个家庭作业,但是我和我的四个朋友都没有找到解决这个问题的方法,我们希望有人更有才华比我们会给我们一些关于它的指示和/或cmets。

让我们从有问题的作业开始(它分为两部分,这是我们无法弄清楚的最后一部分):

首先,创建一个使用 DBMS_UTILITY.GET_TIME 获取当前时间的过程,然后执行复杂的计算。最后,说明获得结果/得到答案需要多长时间(以秒为单位)。

我们通过创建一个计算素数的 for 循环很好地解决了这个问题(计算从 1 到 5000 的每个素数大约需要 5 秒),但是,最后一部分是这样说的:

现在,创建一个包含此复杂计算的包,然后重新编写您的过程,以便调用该计算的“包方法”。您的程序现在将只测量开始时间,调用包含计算的包,并显示获得结果/到达答案所花费的时间(以秒为单位)。

因此,回顾一下:该过程将测量包进行计算所需的时间。这就是我们陷入困境的地方。网上关于这方面的信息不多,但我的代码如下所示:

SET SERVEROUTPUT ON

CREATE OR REPLACE PROCEDURE time_measure_procedure 
AS 
  time_start   NUMBER; 
  time_end     NUMBER; 
  time_diff    NUMBER; 
BEGIN 
    time_start := dbms_utility.get_time;

    --This is where I'd presumably call in the 
    --package into the procedure, whereas the time 
    --will be measured until the calculation is done.
    heavy_calculation_package;

    time_end := dbms_utility.get_time; 
    time_diff := ( time_end - time_start ) / 100; 
    dbms_output.Put_line('Time it took: ' || time_diff || ' seconds.'); 

END time_measure_procedure;
/

CREATE OR REPLACE PACKAGE BODY heavy_calculation_package
AS 
  PROCEDURE time_measure_procedure 
  IS 
    x        NUMBER; 
    counter  NUMBER; 
  BEGIN 
      --This is the prime number calculation, which 
      --we're supposed to call into the procedure.
      FOR n IN 1 .. 5000 LOOP 
          counter := 0; 
          x := Floor(n / 2); 

          FOR i IN 2 .. x LOOP 
              IF ( MOD(n, i) = 0 ) THEN 
                counter := 1; 
              END IF; 
          END LOOP; 

          IF ( counter = 0 ) THEN 
            dbms_output.Put_line(n ||' is a prime number.'); 
          END IF; 
      END LOOP; 
  END time_measure_procedure; 
END heavy_calculation_package; 
/ 

我收到的错误通常是:

对象 package_heavy_calc 无效 没有规范就无法编译 package_heavy_calc 的主体

有没有人知道为什么这不起作用?任何提示或指针都会很可爱!

【问题讨论】:

除了需要包规范外,您在独立过程中的调用还需要是heavy_calculation_package. time_measure_procedure。您不直接调用包,而是调用其中的函数或过程,必须在规范中声明。 【参考方案1】:

在调用之前,您需要使包处于有效状态。在这种情况下,您需要先像这样声明包:

CREATE OR REPLACE PACKAGE package_heavy_calc 
AS 
  PROCEDURE heavy_calc;
END PACKAGE_HEAVY_CALC;

你可以有一个没有主体的包,但不能有一个没有包的主体。您可以通过将代码放在包头中来做到这一点。为您的目的声明包和包体,要容易得多。

顺便说一下,命名对于可读性好的代码至关重要。我会把你的包命名为 PKG_MATH 和过程 P_CALC_PRIME_NUMBERS,所以当你调用它时,你就会知道它的作用。然而,命名就像运动队一样,每个人都有自己喜欢的球队,而且风格可能完全不同。

【讨论】:

但是如果body是空的,包怎么计算呢?哦,对命名错误感到抱歉,我已经将它们从瑞典语翻译成英语,所以它可能把我的头搞砸了,哈哈:) @tobulos1 - 你已经有了身体,你只需要规范就可以了。 “you can have a package without a body...”部分是关于how packages work的一般性陈述;这并不是说在这种情况下您不需要身体。 哦,我明白你的意思了!谢谢!【参考方案2】:

请添加包装规格,然后尝试。下面是一个sn-p 会帮助你的。

      CREATE OR REPLACE PACKAGE package_heavy_calculation
AS
  PROCEDURE heavy_calc;
END package_heavy_calculation;

CREATE OR REPLACE PACKAGE BODY package_heavy_calculation
AS
  PROCEDURE heavy_calc
  IS
    x       NUMBER;
    counter NUMBER;
  BEGIN
    --This is the prime number calculation, which
    --we're supposed to call into the procedure.
    FOR n IN 1 .. 5000
    LOOP
      counter := 0;
      x       := Floor(n / 2);
      FOR i             IN 2 .. x
      LOOP
        IF ( MOD(n, i) = 0 ) THEN
          counter     := 1;
        END IF;
      END LOOP;
      IF ( counter = 0 ) THEN
        dbms_output.Put_line(n ||' is a prime number.');
      END IF;
    END LOOP;
  END heavy_calc;
END package_heavy_calculation; 

【讨论】:

嗯,我还是不能让它工作。我得到“未声明的标识符”或其他一些错误。 立即尝试。它在我的工作区中编译并且工作正常。

以上是关于调用封装成过程,Oracle PL/SQL的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE PL/SQL:以最大执行时间调用外部 Oracle PL/SQL 过程

从 PL/SQL 调用另一个 Oracle 数据库中的过程

使用带有布尔输入参数的 PL/SQL 在 oracle 中调用 java 存储过程

带有输入参数的 Oracle JDBC 调用 PL/SQL 过程记录表

Oracle PL/SQL - 由其他团队调用的用于插入数据的过程。正在从 Java 调用过程

ORACLE PL/SQL:使用多个参数调用存储过程函数(DML 查询)