Oracle функция не компилируется - PullRequest
0 голосов
/ 01 августа 2020

Далее вместе с oracle документами: https://oracle-base.com/articles/misc/pipelined-table-functions

Раздел «Сравнение использования памяти» предоставляет следующую функцию, но не удается скомпилировать с ошибкой: ORA-00942: таблица или представление не существует

CREATE OR REPLACE FUNCTION get_stat (p_stat IN VARCHAR2) RETURN NUMBER AS
  l_return  NUMBER;
BEGIN
  SELECT ms.value
  INTO   l_return
  FROM   v$mystat ms,
         v$statname sn
  WHERE  ms.statistic# = sn.statistic#
  AND    sn.name = p_stat;
  RETURN l_return;
END get_stat;

Следующие запросы выполняются успешно.

select * from v$mystat;
select * from v$statname;

SELECT ms.value
FROM   v$mystat ms,
       v$statname sn
WHERE  ms.statistic# = sn.statistic#
AND    sn.name = 'session pga memory';

Кроме того, следующий анонимный блок работает правильно.

declare
  l_return  NUMBER;
BEGIN
  SELECT ms.value
  INTO   l_return
  FROM   v$mystat ms,
         v$statname sn
  WHERE  ms.statistic# = sn.statistic#
  AND    sn.name = 'session pga memory';

  dbms_output.put_line('l_return: ' || l_return);

END;

Что могло ошиблись?

Ответы [ 3 ]

2 голосов
/ 01 августа 2020

Хотя oracle -base - очень хороший сайт с хорошими примерами руководств, это определенно не"oracle docs". Они находятся по адресу https://docs.oracle.com/en/database/oracle/oracle-database/index.html.

Что касается вашей ошибки, непосредственной причиной является либо 1) указанная таблица не существует, либо 2) у вас нет на нее разрешений. Поскольку запрос вне хранимой процедуры работает, мы знаем, что таблица действительно существует. Так что это проблема с разрешениями, и это связано с тем, что разрешения, присущие роли, не применяются в хранимых процедурах. Вам нужно будет предоставить разрешения напрямую пользователю.

1 голос
/ 01 августа 2020

Похоже, вы получили права доступа к этим таблицам (представлениям) через роль . А ты? Если это так, он не будет работать в именованных PL / SQL процедурах (или функциях), но будет работать в анонимных (как вы заметили).

Чтобы это сделать работать в именованных процедурах, вам нужно будет получить привилегии напрямую .

0 голосов
/ 02 августа 2020
• 1000 относятся к тем же элементам (Oracle V $ Views), но вы также поймете разницу между ролями, системными привилегиями и владением.

ТЕСТОВЫЙ СЛУЧАЙ

I создать тестового пользователя с именем test1 с некоторыми базовыми c привилегиями create procedure and create table

SQL> create user test1 identified by "Oracle_1" default tablespace tbtest temporary tablespace temp_group account unlock profile default quota unlimited on tbtest;

User created

SQL> grant create table, create procedure to test1;

Grant succeeded.

SQL> create table t ( c1 number , c2 number ) ;

Table created.

SQL> insert into t values ( 1 , 1 ) ;

1 row created.

Теперь я собираюсь создать процедуру и функцию, которые будут использовать v $ views. Для этого я предоставил test1 право выбора любой словарной системы.

 SQL>  create or replace procedure p
  2  is
  3  n integer;
  4  begin
  5  select count(*) into n from v$session where status = 'ACTIVE' ;
  6* end;
  /

Procedure created.

SQL> create or replace function f_get_count return number
is
n integer;
begin
  select count(*)
  INTO   n
  FROM   v$mystat ms,
         v$statname sn
  WHERE  ms.statistic# = sn.statistic#
  AND    sn.name = 'session pga memory' ;
  return n;
end;
/

Function created

Итак, теперь у нас есть пользователь, который может получить доступ к v $ views, поскольку ему предоставлена ​​системная привилегия SELECT ANY DICTIONARY, можем ли мы проверить, действительно ли все работает, как ожидалось.

SQL> show user
USER is "TEST1"
SQL> select count(*) from v$session ;

  COUNT(*)
----------
        62

SQL> select count(*) from v$mystat ;

  COUNT(*)
----------
      1804

SQL> select count(*) from v$statname ;

  COUNT(*)
----------
      1804

Теперь давайте попробуем вместо этого с процедурами.

SQL> select f_get_count from dual ;

F_GET_COUNT
-----------
          1

SQL> exec p ;

PL/SQL procedure successfully completed.

В приведенном выше случае пользователь, который запускает процедуру, является владелец, поэтому он наследует выполнение своей собственной процедуры от предоставленной ему привилегии создания процедуры. Он также может успешно запустить процедуру и функцию, даже если они содержат v $ views, по той причине, что пользователю была предоставлена ​​непосредственно системная привилегия выбора любого словаря.

Однако то же самое не работает с SELECT_CATALOG_ROLE.

SQL> grant select_catalog_role to test1 ;

Grant succeeded.

SQL> select f_get_count from dual ;
select f_get_count from dual
       *
ERROR at line 1:
ORA-06575: Package or function F_GET_COUNT is in an invalid state


SQL> exec p ;
BEGIN p ; END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object TEST1.P is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

SQL> select count(*) from v$session ;

  COUNT(*)
----------
        63

Как видите, процедура и функция больше не работают, по сути, они стали НЕДЕЙСТВИТЕЛЬНЫМИ. Тем не менее, пользователь по-прежнему может видеть таблицы, поскольку эта привилегия была предоставлена ​​SELECT_CATALOG_ROLE.

Если вы предоставите привилегию напрямую над v $ session, v $ mystat и v $ statname, все вернется к работе как и ожидалось.

SQL> grant select on v_$mystat to test1 ;

Grant succeeded.

SQL> grant select on v_$session to test1 ;

Grant succeeded.

SQL> grant select on v_$statname to test1 ;

Grant succeeded.

SQL> alter function f_get_count compile ;

Function altered.

SQL> alter procedure p compile ;

Procedure altered.

SQL> exec p;

PL/SQL procedure successfully completed.

SQL> select f_get_count from dual ;

F_GET_COUNT
-----------
          1

Если владельцем процедуры является тот, кто ее выполняет, вы можете предоставить привилегию select any словарной системы, хотя я не рекомендую это делать. Предоставление этой привилегии всегда должно выполняться с особой осторожностью.

Попробуйте предоставить привилегии напрямую над реальными v $ представлениями. Лучшим сценарием является создание фиктивного пользователя / пользователя-контейнера, которому принадлежат привилегии и процедура, поэтому вам нужно только предоставить выполнение процедуры остальным пользователям.

...