当我尝试在存储过程中声明目录时,我得到“PLS-00103:遇到符号“CREATE”...”

Posted

技术标签:

【中文标题】当我尝试在存储过程中声明目录时,我得到“PLS-00103:遇到符号“CREATE”...”【英文标题】:I got "PLS-00103 : Encountered the symbol "CREATE" ..." when I try to declare a directory inside a stored procedure 【发布时间】:2020-02-24 10:04:11 【问题描述】:

我正在尝试使用带有“utl_file”的“PL/SQL”创建一个 txt 文件,但我遇到了一些问题。这是我的代码

procedure testFile Is
  out_File Utl_File.File_Type;
  CREATE OR REPLACE DIRECTORY tmp AS 'C:\Users\jsnow\Documents';

  GRANT read, write ON DIRECTORY tmp TO jack;
Begin
  out_file:=utl_file.fopen(tmp,'test.txt','W');
  utl_file.put_line(out_file,'Test!');
  utl_file.fclose(out_file);
  Exception when others then
    Dbms_output.put_line(sqlerrm ||'-------'||Sqlcode);
end testfile;

当我尝试编译这个脚本时,我得到了这个错误:

PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:

          begin function pragma procedure subtype type <an identifier>
          <a double-quoted delimited-identifier> current cursor delete
          exists prior

您知道如何在存储过程中创建文本文件吗? 提前谢谢你。

【问题讨论】:

我只想重申 Littlefoot 的“不要那样做”的评论。试图在一个过程中创建对象并授予权限是非常非常糟糕的设计的证据。没有充分的理由在应用程序构建期间不能/不应该使用简单的 SQL 来完成这些操作。这适用于所有 DDL。 【参考方案1】:

首先,您不应该在程序中执行此操作。在 SQL 级别(不是 PL/SQL)创建目录(并授予权限)。

如果你坚持,那么你将不得不使用动态 SQL,即execute immediate:

procedure testFile Is
  out_File Utl_File.File_Type;
Begin
  execute immediate q'[CREATE OR REPLACE DIRECTORY tmp AS 'C:\Users\jsnow\Documents']';
  execute immediate 'GRANT read, write ON DIRECTORY tmp TO jack';

  -- the rest of your code
end;

【讨论】:

问题是我在编译我的代码后得到了“PLS00201:必须声明标识符“TMP””。 是的,因为您使用了一个以前从未声明过的变量。它代表目录名称,所以 - 尝试使用 out_file:=utl_file.fopen('TMP', 'test.txt', 'W');,即提供目录 name(您使用 create directory 创建)。 执行“CREATE OR REPLACE”命令后出现“ORA-01031:权限不足”。我认为我不允许创建目录。谢谢你的回复。 这也是可能的。目录由特权用户(通常是 SYS)创建。其他用户可以使用它们,这是通过 SYS 授予它权限来完成的。正如我在第一句话中所说:你不应该这样做。以 SYS(或您拥有的任何其他特权用户;如果没有,请联系您的 DBA)连接,创建目录,授予特权,然后在您的 PL/SQL 过程中使用它 还有一件事:如果您想将所有内容切换到 SYS 并在其架构中创建过程,那么不要这样做。 SYS 很特殊,它拥有数据库。如果你在那里搞砸了,你可能会破坏数据库。

以上是关于当我尝试在存储过程中声明目录时,我得到“PLS-00103:遇到符号“CREATE”...”的主要内容,如果未能解决你的问题,请参考以下文章

EXECUTE 识别存储过程,CALL 不识别

存储过程正确运行,但 DataReader 得到错误结果...有时

存储过程有效,但在 c# 中给出无效列

如何修复PUT Invoke-RestMethod中的“401 Unauthorized”错误(试图替换存储过程)

为啥当我尝试打印地图内容时,我得到的是地址而不是值?在 C++ 中

当我尝试通过存储过程插入空值时出现 SqlException