Почему при попытке создать объект каталога с немедленным выполнением я получаю неверный оператор SQL ORA-00900? - PullRequest
1 голос
/ 05 февраля 2020

Я вижу много примеров того, как это возможно в Oracle. Это просто не работает для меня. Oracle 11. Я получаю эту ошибку в строке 15. Спасибо всем!

declare 
v_path nvarchar2(256);
v_object_exists number;
begin
    -- Use the directory Oracle DB provide for tracing.
    select VALUE into v_path from V$DIAG_INFO where NAME = 'Diag Trace';
    --dbms_output.put_line(v_path);

    -- Set up new directory!
    select count(*) into v_object_exists from all_objects where object_name = 'DIAG_TRACE' and object_type = 'DIRECTORY';
    if v_object_exists > 0 then 
        execute immediate 'DROP DIRECTORY DIAG_TRACE'; 
    end if;
    dbms_output.put_line('CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ''' || v_path || '''');
    execute immediate 'CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ''' || v_path || '''';

end;

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Это похоже на ошибку; хотя в MoS нет ни одной из перечисленных в справочной заметке ORA-00900.

Не нравится, когда переменная пути объединяется как часть execute immediate. Это терпит неудачу:

v_path := '/some/path';
execute immediate 'CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ''' || v_path || '''';

, но это нормально, хотя окончательное утверждение остается тем же:

execute immediate 'CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ''/some/path''';

После некоторого поиска это может быть связано с ошибкой 7036176: " СОЗДАННАЯ ДИНАМИ C ИМЯ ОБЪЕКТА ПОДНИМАЕТ ORA-00900 В 10G И 11G ". Это не совсем то же самое, но близко. Для получения дополнительной информации вам потребуется поискать в моей Oracle поддержке, хотя и не так много.

Вы можете обойти ее с помощью переменной:

declare
v_stmt varchar2(256);
v_path nvarchar2(256);
v_object_exists number;
begin
    -- Use the directory Oracle DB provide for tracing.
    select VALUE into v_path from V$DIAG_INFO where NAME = 'Diag Trace';
    --dbms_output.put_line(v_path);
    -- Set up new directory!
    select count(*) into v_object_exists from all_objects where object_name = 'DIAG_TRACE' and object_type = 'DIRECTORY';
    if v_object_exists > 0 then
        execute immediate 'DROP DIRECTORY DIAG_TRACE';
    end if;
    v_stmt := 'CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ''' || v_path || '''';
    dbms_output.put_line(v_stmt);
    execute immediate v_stmt;
end;
/

, которая сохраняет повторы строка для его печати, хотя вы, возможно, сделали это только из-за этой проблемы.

Не уверен, почему вы сначала выбрасываете с or replace, кстати.

0 голосов
/ 05 февраля 2020

Я предпочитаю помещать команду в переменную, отображать ее (для проверки) и затем выполнять:

SQL> declare
  2  v_path nvarchar2(256);
  3  v_object_exists number;
  4  l_str varchar2(200);
  5  begin
  6      -- Use the directory Oracle DB provide for tracing.
  7      select VALUE into v_path from V$DIAG_INFO where NAME = 'Diag Trace';
  8      --dbms_output.put_line(v_path);
  9
 10      -- Set up new directory!
 11      select count(*) into v_object_exists from all_objects where object_name = 'DIAG_TRACE' and object_type = 'DIRECTORY';
 12      if v_object_exists > 0 then
 13          execute immediate 'DROP DIRECTORY DIAG_TRACE';
 14      end if;
 15      l_str := 'CREATE OR REPLACE DIRECTORY DIAG_TRACE AS ' || chr(39) || v_path ||chr(39);
 16      dbms_output.put_line(l_str);
 17      execute immediate l_str;
 18  end;
 19  /
CREATE OR REPLACE DIRECTORY DIAG_TRACE AS
'C:\ORACLEXE\APP\ORACLE\diag\rdbms\xe\xe\trace'

PL/SQL procedure successfully completed.

SQL>

Конечно, вы должны запускать ее как привилегированный пользователь (такой как SYS).

...