Oracle软件包并在公共变量中使用select语句

时间:2018-11-12 04:56:30

标签: oracle plsql package

一直在搜寻年龄无济于事。在评估的一部分中,它指定我们必须在一个包内声明一个公共变量(因此,请勿尝试告诉我使其成为一个独立的函数...),即来自另一个表的行数(“ SELECT COUNT(* )FROM A2_GUESTS“是提示)

我可以很容易地将公共变量设置为静态数字,但是,如果我尝试添加select语句,则会引发错误。

如果我尝试在程序包主体中分配它,那么它也会引发错误,如果我将其包装在“ begin”和“ end”中,则它会太早终止程序包主体。

CREATE OR REPLACE PACKAGE Beachcomber
AS
    v_Guest_Count NUMBER := 0; 
END Beachcomber;
/
CREATE OR REPLACE PACKAGE BODY Beachcomber IS
    SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS; -- doesn't work
    v_Guest_Count NUMBER := SELECT COUNT(*) FROM A2_GUESTS; -- doesn't work
    BEGIN
        v_Guest_Count NUMBER := SELECT COUNT(*) FROM A2_GUESTS; 
    END; -- doesn't work - ends the package prematurely
END Beachcomber;

以上示例是我一直在尝试的方法(以及其他方法),而不是同时进行,而是逐一进行。

我们得到了对其进行测试的代码:(一定不要更改此测试代码)

PROMPT 
PROMPT TESTING: Initialisation of the v_Guest_Count variable.  Expect 81.
BEGIN
   DBMS_OUTPUT.PUT_LINE('v_Guest_Count has been initialised to: '||TO_CHAR(BEACHCOMBER.v_Guest_Count));
END;

非常感谢任何帮助,我发现有人在2015年曾在这里提出过此问题,但唯一的答案是使它具有功能性,因此他们调整了测试代码,因此无济于事。

软件包中包含更多具有过程和功能的代码:

CREATE OR REPLACE PACKAGE Beachcomber
IS
    v_Guest_Count NUMBER := 0; 
    PROCEDURE ADD_GUEST 
        (p_guest_name A2_GUESTS.guest_name%TYPE,
        p_guest_address A2_GUESTS.guest_address%TYPE);
END Beachcomber;
/
    CREATE OR REPLACE PACKAGE BODY Beachcomber IS
    BEGIN 
    SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS;

    PROCEDURE ADD_GUEST
        (p_guest_name A2_GUESTS.guest_name%TYPE,
        p_guest_address A2_GUESTS.guest_address%TYPE)
        IS BEGIN
        INSERT INTO A2_GUESTS (Guest_ID, Guest_Name, Guest_Address) 
            VALUES (guest_id_seq.NEXTVAL, p_guest_name, p_guest_address);
        v_Guest_Count := v_Guest_Count +1;
    END ADD_GUEST;
END Beachcomber;

这将抛出:

5/5 PLS-00103: Encountered the symbol "PROCEDURE" 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 The symbol "declare" was substituted for "PROCEDURE" to continue.

我通常可以从错误消息中解决它,但是oracle错误消息也可以用荷兰语写给我:/

2 个答案:

答案 0 :(得分:2)

我们可以通过将代码放在正文末尾来将初始化代码包含在包中。它采用BEGIN块的形式,并以程序包主体的最后一个END终止。

create or replace package BEACHCOMBER is
    v_Guest_Count pls_integer;
    function get_cnt return number;
end BEACHCOMBER;
/
create or replace package body BEACHCOMBER is
    function get_cnt return number
    is
    begin
        return v_Guest_Count;
    end get_cnt;

<< init_block >>
begin
    select count(*) 
    into v_Guest_Count
    from A2_GUESTS;
end BEACHCOMBER;
/

标签<< init_block >>下的代码在第一次调用该程序包时运行。这包括引用公共变量。除非重新编译软件包,否则该代码不会在会话中再次运行,这会丢弃状态。

这是我的测试脚本。我已经将此版本发布为Oracle LiveSQL上的有效演示(因为DBMS_OUTPUT),但是您需要一个免费 Oracle帐户来运行它。 Check it out

测试设置

drop table A2_GUESTS
/

create table A2_GUESTS (id number);

insert into A2_GUESTS select level from dual connect by level <=23;

create or replace package BEACHCOMBER is
    v_Guest_Count pls_integer;
    function get_cnt return number;
end BEACHCOMBER;
/
create or replace package body BEACHCOMBER is
    function get_cnt return number
    is
    begin
        return v_Guest_Count;
    end get_cnt;
begin
    select count(*) 
    into v_Guest_Count
    from A2_GUESTS;
end BEACHCOMBER;
/

这是测试;

begin
    dbms_output.put_line('count = ' || BEACHCOMBER.v_Guest_Count);
end;
/

insert into A2_GUESTS values (42)
/

select BEACHCOMBER.get_cnt 
from dual
/

alter package BEACHCOMBER compile body
/

select BEACHCOMBER.get_cnt 
from dual
/

答案 1 :(得分:1)

您必须在包主体中设置Package变量。您无需在主体中局部声明另一个变量。

CREATE OR REPLACE PACKAGE BODY Beachcomber IS
    BEGIN
        SELECT COUNT(*) INTO v_Guest_Count FROM A2_GUESTS; 
END Beachcomber;
/

然后您可以在任何其他PL / SQL块中访问该变量。

SET SERVEROUTPUT ON
BEGIN
  DBMS_OUTPUT.PUT_LINE(Beachcomber.v_Guest_Count); 
end;
/

0

PL/SQL procedure successfully completed.

编辑

您应该像在外部调用过程一样将查询放入过程中。

CREATE OR REPLACE PACKAGE BODY beachcomber IS
     PROCEDURE add_guest (
          p_guest_name      a2_guests.guest_name%TYPE,
          p_guest_address   a2_guests.guest_address%TYPE
     )
          IS
     BEGIN
          SELECT COUNT(*)
           INTO v_guest_count
          FROM a2_guests;

          INSERT INTO a2_guests (
               guest_id,
               guest_name,
               guest_address
          ) VALUES (
               guest_id_seq.NEXTVAL,
               p_guest_name,
               p_guest_address
          );
          v_guest_count := v_guest_count + 1;
     END add_guest;
END beachcomber;
/

EDIT2 :使用主要过程进行初始化。

CREATE OR REPLACE PACKAGE beachcomber IS
     v_guest_count NUMBER := 0;
     PROCEDURE main;
     PROCEDURE add_guest (
          p_guest_name      a2_guests.guest_name%TYPE,
          p_guest_address   a2_guests.guest_address%TYPE
     );
END beachcomber;
/ 
CREATE OR REPLACE PACKAGE BODY beachcomber IS
     PROCEDURE add_guest (
          p_guest_name      a2_guests.guest_name%TYPE,
          p_guest_address   a2_guests.guest_address%TYPE
     )
          IS
     BEGIN
          INSERT INTO a2_guests (
               guest_id,
               guest_name,
               guest_address
          ) VALUES (
               guest_id_seq.NEXTVAL,
               p_guest_name,
               p_guest_address
          );
          v_guest_count := v_guest_count + 1;
     END add_guest;
     PROCEDURE main
          IS
     BEGIN
          SELECT COUNT(*)
          INTO v_guest_count
          FROM a2_guests;
     END main;
END beachcomber;
/

执行程序。

BEGIN
  beachcomber.main;
  beachcomber.add_guest('Sherlock','221b baker street');
END;
/