李威 さぽている

小说翻译,日语相关转移至http://blog.hjenglish.com/liwei

UTL_FILE使用配置篇


以前曾写过PL/SQL,当时还是第一次接触,什么都不明白
顺手写了篇 《Oracle内建包UTL_FILE使用说明 》的博文,没想到还被转载(譬如百度搜索utl_file,第一篇就是,不过没写我的出处,可惜……)
http://www.blogjava.net/liwei/archive/2007/01/10/92902.html

当时项目做完就没接触PL/SQL了,时隔2年半,又要写PL/SQL了,而且遇到的问题居然还是和UTL_FILE有关。
于是上网找了些资料
http://www.shift-the-oracle.com/plsql/utl_file/utl_file_dir.html
http://www.shift-the-oracle.com/plsql/utl_file/create-directory.html
日文的,不得不说,日本人做事实在是认真,资料非常详细,看完之后,我就觉得我是高手了,可以整理点东西出来教别人了……哈哈
废话少说,开始

现在一般跑UTL_FILE.FOPEN时会出现ORA-29280的错误,出现这个错误主要有2个原因
1.文件夹没有读写权限
2.文件夹没有进行Oracle读写配置

注意:这里讨论的Oracle是在Unix类(包括linux,Solaris等)主机下安装的。

对于第1个原因,直接设定文件夹权限即可,譬如
# chmod 700 /u05/file_storage/recv_dir
这个没啥好说,不是我要说的重点。
第2个原因,可以好好说说。
Oracle进行文件夹读写配置有2种方式
1.设定UTL_FILE_DIR
2.使用DIRECTORY 对象

1.设定UTL_FILE_DIR
Oracle 8i之前,貌似没有DIRECTORY这个概念,所以只有一种方式。
编辑 initORACLE_SID.ora 文件(ORACLE_SID是个变数,因DB设定有所不同),添加
UTL_FILE_DIR='/u05/file_storage/recv_dir','/u05/file_storage/send_dir'
即可。
Oracle 9i之后还可以利用ALTER SYSTEM 命令进行设定
ALTER SYSTEM SET
  UTL_FILE_DIR='/u05/file_storage/recv_dir','/u05/file_storage/send_dir'
SCOPE = SPFILE ;
也可以用命令来确认设定是否正确
SELECT NAME, VALUE FROM V$PARAMETER2 WHERE NAME='utl_file_dir' ;

注意:Oracle 8i 之后的DB不推荐使用这种方式,主要是情报泄露方面,日本很在意这个。
另外,让所有文件夹有效可使用('*')。
这种方法不方便的就是,设定了之后必须重启Oracle才能使设定有效。


使用例

CREATE OR REPLACE PROCEDURE RIVUS.UTL_FILE_DIR_WRITE_SAMPLE
AS
 vHandle  UTL_FILE.FILE_TYPE;
 vDirname VARCHAR2(250);
 vFilename VARCHAR2(250);
 vOutput  VARCHAR2(32767);
BEGIN
 vDirname := '/u05/file_storage/send_dir';   -- 绝对路径
 vFilename := 'test.txt';
 vHandle := UTL_FILE.FOPEN(vDirname ,vFilename,'w', 32767);
 
 vOutput := '利用 UTL_FILE_DIR 进行的文件处理';
 UTL_FILE.PUT_LINE(vHandle, vOutput);
 UTL_FILE.FCLOSE(vHandle);
EXCEPTION WHEN OTHERS THEN
 UTL_FILE.FCLOSE_ALL;
 RAISE;
END;

2.使用DIRECTORY 对象
从Oracle 9i 开始UTL_FILE就能使用CREATE DIRECTORY了。
首先文件夹必须存在,要有权限,我就不多说了。
然后做成DIRECTORY 对象
CREATE DIRECTORY recv_area AS '/u05/file_storage/recv_dir';
CREATE DIRECTORY send_area AS '/u05/file_storage/send_dir';

当recv_area已存在时,会出错,可使用下面这句
CREATE OR REPLACE DIRECTORY recv_area AS '/u05/file_storage/recv_dir';

接着,赋予用户该DIRECTORY 对象的读写权限
GRANT READ ON DIRECTORY recv_area TO user_name ;
GRANT WRITE ON DIRECTORY send_area TO user_name ;

同时读写权限
GRANT READ,WRITE ON DIRECTORY recv_area TO user_name ;

做好这些就可以确认了
SELECT * FROM ALL_DIRECTORIES ;
看到自己做成的DIRECTORY了吧
这里需要注意的是,当初CREATE DIRECTORY的时候是小写recv_area,现在这里是大写RECV_AREA
之后利用该DIRECTORY 对象时必须用大写。
还有,该DIRECTORY对象不包括上层目录(这个是当然的),也不包括子目录。
要利用子目录需要再定义一个子目录的DIRECTORY对象。

使用例

CREATE OR REPLACE PROCEDURE RIVUS.CREATE_DIR_WRITE_SAMPLE
AS
 vHandle  UTL_FILE.FILE_TYPE;
 vDirname VARCHAR2(250);
 vFilename VARCHAR2(250);
 vOutput  VARCHAR2(32767);
BEGIN
 vDirname := 'SEND_AREA';   -- 必须用大写
 vFilename := 'test.txt';
 vHandle := UTL_FILE.FOPEN(vDirname ,vFilename,'w', 32767);
 
 vOutput := '利用CREATE DIRECTORY进行的文件处理';
 UTL_FILE.PUT_LINE(vHandle, vOutput);
 UTL_FILE.FCLOSE(vHandle);
EXCEPTION WHEN OTHERS THEN
 UTL_FILE.FCLOSE_ALL;
 RAISE;
END;

到此为止,问题应该解决了。

posted on 2009-12-17 19:10 李威 阅读(532) 评论(1)  编辑  收藏

评论

# re: UTL_FILE使用配置篇 2010-01-26 00:15 zhaogaifang

李威,你太强了!我找了一晚上,终于在你这找到解决方法了,太感激了!  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: