【问题标题】:Executing PL/SQL functions from a file从文件执行 PL/SQL 函数
【发布时间】:2015-02-11 17:13:21
【问题描述】:

我正在使用 SQL*Plus 并且有一个名为 functions.sql 的文件,其中包含 3 个 PL/SQL 函数:

create or replace function getcustnamebyid (id number) return varchar2(30)
 is
   ...
 begin
   ...
 end;
/

create or replace function getspcommbyid (id number) return float
 is
   ...
 begin
   ...
/

create or replace function iscommok (comm float) return boolean
 is
   ...
 begin
   ...
 end;
/

我试图在driver.sql 程序中调用这些函数。我尝试了以下方法,但得到 PL/SQL: ORA-00904: "FUNCTIONS"."GETCUSTNAMEBYID": invalid identifier 错误。这两个文件在同一个目录下,如何从driver.sql 调用我在functions.sql 中定义的函数?过程也可以这样调用吗?

driver.sql:

declare
  name varchar2(30);
  comm float;
  commok boolean;
begin
  select functions.getcustnamebyid(100)
  into name
  from dual;
  dbms_output.put_line('Hi ' || name );
end;
/

【问题讨论】:

    标签: oracle plsql sqlplus


    【解决方案1】:

    你没有。

    函数是一个数据库对象;这意味着它是compiled on the database。在使用函数之前,您首先需要编译它们 - 您可以执行从 SQL*Plus 获得的 .sql 文件,例如:

    sqlplus username/password@db @ driver.sql
    

    这将在您的数据库中创建(或替换它们已经存在的函数)。

    在每个函数创建后添加 SQL*Plus 命令show errors 也是值得的,这样如果有任何错误,您可以看到它们。

    【讨论】:

    • 所以我必须在运行 driver.sql 之前运行 functions.sql 并且 driver.sql 自身无法运行 functions.sql?
    • 没错@Julio;您需要确保函数存在于数据库中,然后才能使用它们。
    • 其实你可以在driver.sql的开头(declare之前)加上@functions.sql。这是 SQL*Plus 运行其他文件的指令。但是,您最好还是部署一次功能,而不是每次要使用它们时都重新部署。
    • 这更像是对 cme​​ts 的回应。可以让 driver.sql 运行 functions.sql。它不会做 OP 真正想要的,但你当然可以从另一个脚本中调用一个脚本。
    【解决方案2】:

    在 PL/SQL 中,必须在要使用它们的上下文中创建函数。通常这是通过在数据库中创建对象来完成的,因为建议使用其他答案。如果您出于某种原因真的反对创建数据库对象,您实际上可以将它们的范围限制在您的 PL/SQL 块中:

    DECLARE
       FUNCTION getcustnamebyid (id NUMBER)
          RETURN VARCHAR2 IS
       BEGIN
          RETURN NULL;
       END;
    
       name VARCHAR2 (30);
    BEGIN
       name := getcustnamebyid (100);
       DBMS_OUTPUT.put_line ('Hi ' || name);
    END;
    /
    

    您不能以这种方式引用另一个文件中的函数,但它确实允许您在不持久化的情况下使用这些函数。对这种方法的一个警告是,您将只能在过程代码中使用这些函数; SQL 只能引用作为数据库对象创建的函数。

    【讨论】:

      【解决方案3】:

      问题的根源在于您的函数调用

      假设我们在模式 scott(标准示例模式)中创建函数 get_hello_world。

      SCOTT@erp> 
      
        1  CREATE OR REPLACE FUNCTION get_hello_world RETURN VARCHAR2
        2  IS
        3  BEGIN
        4    RETURN 'hello world';
        5* END get_hello_world;
      SCOTT@erp> /
      
      Function created.
      
      SCOTT@erp> commit;
      

      接下来我们创建一个 driver.sql 文件。这是我的例子:

      BEGIN
        dbms_output.put_line(scott.get_hello_world);
      END;
      

      接下来,我们要在驱动文件中调用它:

      SCOTT@erp> @driver.sql
        4  /
      hello world
      
      PL/SQL procedure successfully completed.
      

      虽然您的新对象 scott.get_hello_world 是函数类型的新数据库对象,但我们不使用“函数”一词来限定我们的调用。

      您收到错误PL/SQL: ORA-00904: "FUNCTIONS"."GETCUSTNAMEBYID": invalid identifier,因为未正确引用 scott 架构中新编译的数据库对象 get_hello_world

      最后,如果我们在使用 scott 数据库帐户时调用它,我们可以通过所有者 scott 来限定我们的调用。

      【讨论】:

        【解决方案4】:

        迟到了,但你可以“包含”包含一些函数的文件,然后调用它们,例如,

        helper_functions.sql

        procedure Echo(AValue in varchar2) is
        begin
          dbms_output.put_line(AValue);
        end;
        

        driver.sql

        set serveroutput on
        declare
          @@helper_functions.sql
        begin
          Echo('hello');
        end;
        /
        

        这里的输出是

        SQL> @@driver.sql
        hello
        
        PL/SQL procedure successfully completed.
        

        【讨论】:

          猜你喜欢
          • 2013-04-01
          • 2012-11-19
          • 2014-10-28
          • 1970-01-01
          • 2021-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-29
          相关资源
          最近更新 更多