【问题标题】:Join between a collection and a table集合和表之间的连接
【发布时间】:2016-03-29 21:47:12
【问题描述】:

我对 PL/SQL 中的过程有疑问。我在包中声明了一个公共过程,我想在第一个过程中调用另一个过程(私有)。

PROCEDURE show_notesforstudent (number_id IN number) as
    ...
    DBMS_OUTPUT.PUT_LINE('The notes for the student with number_id X are: '|| Y);

    DBMS_OUTPUT.PUT_LINE('here is the call for the private procedure');
    erase_student(number_id);
END;

这段代码是一个通用的例子,我的代码比较大,这里放不下。这里只是主要思想。 对于此调用,我遇到此错误:“错误(31,5):PLS-00313:'erase_student' 未在此范围内声明”。

erase_student 程序的实现是:

PROCEDURE erase_student(n_id students.number_id%type) AS
  student_inexistent EXCEPTION;
  PRAGMA EXCEPTION_INIT(student_inexistent, -20002);
  counter integer;
BEGIN
  SELECT COUNT(nmber_id) INTO counter FROM studens where number_id = n_id;
  IF counter = 0 THEN
      raise student_inexistent;
  END IF;
  DELETE FROM students WHERE number_id = n_id;
  EXCEPTION
  WHEN student_inexistent THEN
      raise_application_error (-20002, 'Student with number_id' || n_id ||        '     doesn't exists in database');
END stergere_student;`

【问题讨论】:

  • show_notesforstudent 之前声明erase_student 过程或在过程开始时使用erase_student 标头的前向声明。
  • 可能由于erase_students 中的语法错误,erase_student 不存在。看来SELECT COUNT(*)... 中的表名应该是students 而不是studens。此外,过程的名称 (erase_student) 与 END stergere_student 语句中的名称不匹配。翻译时可能会出现问题(来自罗马尼亚语?)。此外,在RAISE_APPLICATION_ERROR 调用中,doesn't 中的撇号应该加倍(doesn''t),这样您就可以在字符串文字中得到一个撇号。祝你好运。
  • 我也对标题和问题的关系感到困惑。在您的标题中,您正在谈论想要加入一个集合。我在您的问题正文中没有看到任何引用集合的内容。
  • 我犯了一个错误..我想发布另一个问题,但标题仍然存在..抱歉

标签: oracle plsql


【解决方案1】:

让我们简化您的代码并使其语法正确:

CREATE OR REPLACE PACKAGE package_name
AS
  PROCEDURE show_notesforstudent (number_id IN number);
END;
/

CREATE OR REPLACE PACKAGE BODY package_name
AS
  PROCEDURE show_notesforstudent (number_id IN number)
  AS
  BEGIN
      erase_student(number_id);
  END;

  PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; 
END;
/

但是,当我们得到PLS-00313: 'ERASE_STUDENT' not declared in this scope 时,它仍然无法编译。可以通过重新组织包来修复它,以确保私有过程在被调用之前被声明;像这样:

CREATE OR REPLACE PACKAGE BODY package_name
AS
  PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body

  PROCEDURE show_notesforstudent (number_id IN number)
  AS
  BEGIN
      erase_student(number_id);
  END;
END;
/

但是,如果你想保持包中过程的顺序,那么你可以使用前向声明在私有过程被调用之前声明头,然后声明主体;像这样:

CREATE OR REPLACE PACKAGE BODY package_name
AS
  PROCEDURE erase_student(n_id NUMBER); -- Header only

  PROCEDURE show_notesforstudent (number_id IN number)
  AS
  BEGIN
      erase_student(number_id);
  END;

  PROCEDURE erase_student(n_id NUMBER) AS BEGIN NULL; END; -- Header and body
END;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 2013-04-27
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多