【问题标题】:How to execute package with parameter如何执行带参数的包
【发布时间】:2019-04-29 15:50:25
【问题描述】:

我有两张桌子:

students(student_id, first_name, last_name)
classes(classid, incharge_student_id)

我编写了一个包,它将classid 作为参数,然后为每个班级表的incharge_student_id 从学生表中打印student_id, first_name, last_name

CREATE OR REPLACE PACKAGE pack1
AS
PROCEDURE show_info(c_id classes.classid%TYPE DEFAULT 1, show_info_recordset OUT SYS_REFCURSOR);

END pack1;
/
CREATE OR REPLACE PACKAGE BODY pack1
AS
    PROCEDURE show_info 
    (   
    c_id   NUMBER DEFAULT 1,
    show_info_recordset OUT SYS_REFCURSOR
    )
    IS
       v_first_name students.first_name%TYPE;
       v_last_name students.last_name%TYPE;
       v_students students.student_id%TYPE;
    BEGIN
       SELECT students.first_name, students.last_name, students.student_id
         INTO v_first_name, v_last_name, v_students
         FROM students, classes
         WHERE (classes.classid = c_id AND classes.incharge_student_id=students.student_id);
       DBMS_OUTPUT.PUT_LINE('Class ID: ' || c_id);
       DBMS_OUTPUT.PUT_LINE('FIRST NAME: ' || v_first_name);
       DBMS_OUTPUT.PUT_LINE('LAST NAME: ' || v_last_name);
       DBMS_OUTPUT.PUT_LINE('student_id: ' || v_students);
    EXCEPTION
       WHEN NO_DATA_FOUND THEN
          DBMS_OUTPUT.PUT_LINE('Class ID: ' || c_id || ' not found.');
    END;
END pack1;
/

我收到警告消息

Package Body created with compilation errors.

我对 pl/sql 很陌生,想知道为什么会收到错误消息,然后还想知道如何执行一个有参数的包。

我知道如何执行普通包:

variable x refcursor;
exec package_name.procedure_name ( :x );
print x;

但是我将如何使用参数执行我上面的包

【问题讨论】:

    标签: oracle stored-procedures plsql package


    【解决方案1】:

    您的代码中有几个错误,见下文:

    CREATE OR REPLACE PACKAGE pack1
    AS
    PROCEDURE show_info(c_id classes.classid%TYPE, show_info_recordset OUT SYS_REFCURSOR);
    
    END pack1;
    /
    CREATE OR REPLACE PACKAGE BODY pack1
    AS
        PROCEDURE show_info 
        (   
        c_id   NUMBER DEFAULT -1,
    

    正文中c_id参数的规范与规范中的规范不匹配。将其更改为c_id classes.classid%type default 1,并将default 1 限定符添加到井上方的规范中。

        show_info_recordset OUT SYS_REFCURSOR
        )
        IS
           v_first_name IN students.first_name%TYPE;
           v_last_name IN students.last_name%TYPE;
           v_students IN students.student_id%TYPE;
    

    删除变量声明中的“IN”关键字。它仅用于参数声明。

        BEGIN
           SELECT students.first_name, students.last_name, students.student_id
             INTO v_first_name, v_last_name, v_students.student_id
    

    在子句中引用 v_students 而不是 v_students.student_id

             FROM students, classes
             WHERE (classes.classid = c_id AND classes.incharge_student_id=students.student_id;);
    

    右括号内有一个额外的分号 (;)。删除它。

           DBMS_OUTPUT.PUT_LINE('Class ID: ' || c_id);
           DBMS_OUTPUT.PUT_LINE('FIRST NAME: ' || v_first_name);
           DBMS_OUTPUT.PUT_LINE('LAST NAME: ' || v_last_name);
           DBMS_OUTPUT.PUT_LINE('student_id: ' || v_students);
        EXCEPTION
           WHEN NO_DATA_FOUND THEN
              DBMS_OUTPUT.PUT_LINE('Class ID: ' || c_id || ' not found.');
        END;
    END pack1;
    /
    

    要执行此代码,您只需要传入附加参数,或者使用@Littlefoot 提到的命名参数,但由于您没有将光标分配给 out 参数,因此不会打印任何内容。

    【讨论】:

    • 感谢您指出错误...以上我已经进行了更改。但是我仍然收到show_info is declared in package spec and must be defined in package body13/5 SQL statement ignored14/36 invalid reference to variable v_students15/4 invalid identifier之类的错误。我不明白为什么我会收到这些错误
    • 您是否在规范和正文中对 c_id 进行了两次编辑?此外,我错过了您的 INTO 子句中的一个错误,我现在已在上面的代码中指出了该错误。
    • 我对 into 子句进行了更改。是的,我完全按照你在正文中所说的c_id classes.classid%type default 1c_id NUMBER DEFAULT 1, 做的。您可以在我上面的代码中看到更改。现在也只有 1 个错误,show_info is declared in a package specification and must be defined in the package body
    • 在你的身体里你仍然有c_id number而不是c_id classes.classid%type,它们需要在规范和正文中完全匹配。
    • 谢谢先生。它现在正在工作。但在执行中只是多了一项帮助。 variable info refcursor;exec pack1.show_info(A001, :info);我正在做就像上面Littlefoot所说的那样,但它表明必须声明'A001'。这位先生做错了什么。
    【解决方案2】:

    如果您使用 SQL*Plus,请执行

    SQL> show err
    

    编译包后;它会将您指向导致错误的行。例如:

    SQL> create or replace procedure p_test is
      2  begin
      3    select 1 from dual;
      4  end;
      5  /
    
    Warning: Procedure created with compilation errors.
    
    SQL> show err
    Errors for PROCEDURE P_TEST:
    
    LINE/COL ERROR
    -------- -----------------------------------------------------------------
    3/3      PLS-00428: an INTO clause is expected in this SELECT statement
    SQL>
    

    如果您使用 GUI,它可能包含您可以检查的“错误”选项卡(并获得相同的信息)。

    在调用带有参数的过程时:只需包含它们,例如

    variable x refcursor;
    exec package_name.procedure_name (100, :x );
    print x;                           ^
                                       |
                                      this is the first procedure's parameter
    

    【讨论】:

    • 我正在使用 sqlplus.... 我收到以下错误:9/18 PLS-00103: Encountered the symbol "IN" when expecting one of the following: constant exception <an identifier> <a double-quoted delimited-identifier> table long double ref char time timestamp interval date binary national character nchar 9/45 PLS-00103: Encountered the symbol ";" when expecting one of the following: . ( * @ % & - + / at loop mod remainder rem .. <an exponent (**)> || multiset
    • 你声明的变量不应该有IN,例如v_first_name students.first_name%TYPE;
    • 删除 IN13/5 PL/SQL: SQL Statement ignored 16/27 PL/SQL: ORA-00907: missing right parenthesis 16/70 PLS-00103: Encountered the symbol ")" when expecting one of the following: (begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge 后出错
    • 25/5 PLS-00103: Encountered the symbol "pack1" when expecting one of the following: ;
    • Oracle 会告诉您您需要知道的一切。我真的必须翻译每一步,例如“在第 16 行,第 70 位,有一个不应该存在的封闭括号”吗?我没有你的表,所以在我的数据库中运行你的代码是没有用的(我不会创建表只是为了为你调试代码)。
    【解决方案3】:

    删除变量名后的 IN ,您需要运行 PROCEDURE 而不是包,这也是为什么您要在您的情况下定义一个过程,最好让它发挥作用

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 2014-07-20
      • 2012-02-24
      • 2015-03-21
      相关资源
      最近更新 更多