【问题标题】:Why am I getting ORA-00900 Invalid SQL statement when trying to create a directory object with execute immediate?为什么我在尝试使用立即执行创建目录对象时收到 ORA-00900 Invalid SQL statement?
【发布时间】:2020-05-21 17:56:41
【问题描述】:

我在 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;

【问题讨论】:

  • 文件系统目录的权限问题?可以直接从你的界面(sqldeveloper、sqlplus、sqlci)执行吗?
  • @JeffHolt - DROP DIRECTORY 永远不会触及实际的操作系统文件系统。被删除的目录只是数据库中的一个对象......操作系统文件系统上目录的别名。
  • @EdStevens 是的,但 OP 说第 15 行是创建,而不是删除。
  • @JeffHolt - 这也适用于创建。在您尝试使用目录(即读/写)之前不会评估操作系统端 - 这可能有点令人困惑。路径在创建时甚至没有经过验证。
  • 是的,如果我手动运行它,我可以很好地运行该语句。

标签: oracle ddl execute-immediate


【解决方案1】:

这似乎是一个错误;虽然没有在关于 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 有关:“CONCATENATED DYNAMIC OBJECT NAME RAISES ORA-00900 IN 10G & 11G”。它不完全相同,但很接近。您需要查看 My Oracle Support 以获取更多信息,但信息不多。

你可以用一个变量来解决它:

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

【讨论】:

  • 这太棒了!我尝试了这个,但将我的 v_stmt 设置为 nvarchar2。事实证明,立即执行不喜欢那样!我将原始脚本变量更改为 varchar2 并且它可以工作!谢谢!
  • 回复:或替换和删除:这就是 Toad 出于某种原因自动生成的内容。我使用默认脚本作为我的基线。
【解决方案2】:

我更喜欢将命令放入变量中,显示(用于验证)然后执行:

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)的身份运行它。

【讨论】:

    猜你喜欢
    • 2016-10-09
    • 1970-01-01
    • 2014-01-09
    • 2018-02-27
    • 2021-11-02
    • 2016-08-31
    • 1970-01-01
    • 2021-10-28
    • 2018-02-25
    相关资源
    最近更新 更多