Oracle Packages и использование оператора select в публичной переменной - PullRequest
0 голосов
/ 12 ноября 2018

Искал веками безрезультатно. В части оценки указывается, что мы должны объявить открытую переменную WITHIN в пакете (поэтому не пытайтесь указывать мне сделать ее автономной функцией ...), которая представляет собой количество строк в другой таблице ("SELECT COUNT (* ) ОТ A2_GUESTS "это подсказка)

Я могу достаточно легко установить общедоступную переменную в виде статического числа, однако, если я пытаюсь добавить оператор выбора, он выдает ошибку.

Если я пытаюсь назначить его в теле пакета, он также выдает ошибку, если я заключаю его в «начало» и «конец», он завершает тело пакета слишком рано.

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.

Обычно я в порядке, работая с сообщениями об ошибках, но сообщения об ошибках оракула могут быть написаны мне на голландском: /

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Мы можем включить инициализирующий код в пакет, поместив его в конце тела . Он принимает форму блока 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 для ее запуска. Проверьте это

Тестовая установка

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
/
0 голосов
/ 12 ноября 2018

Вы должны установить переменную 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.

EDIT

Вы должны помещать запросы в процедуру, как если бы вы вызывали процедуру извне.

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;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...