Deliberate
Oracle代码本身有意依赖于异常工作,这意味着必须预计到有异常发生,并为异常编码。
示例: 从文件中,一行一行的读取文本,读到文尾时触发no_data_found异常,再关闭文件句柄。
create or replace procedure read_file(dir_in in varchar2,file_in in varchar2) is l_file utl_file.file_type; l_line varchar2(32767); begin l_file := utl_file.fopen(dir_in,file_in,'r',32767); -- 在循环体中,get_line(),从文件中一行行的读取,当读到最后时,触发no_data_found 异常 loop utl_file.get_line(l_file,l_line,32767); dbms_output.put_line(l_line); end loop; exception -- 在异常中,关闭文件句柄 when no_data_found then utl_file.fclose(l_file); dbms_output.put_line('Good'); end read_file;
小结:
在loop循环体中没有使用exit退出循环,而是在get_line() 读到最后文尾时触发了NO_DATA_FOUND异常,并在异常中关闭了文件句柄。该异常是我们可预见的、期待的。
ERROR参考如下:
一、创建完过程时发生sysdba 未对当前用户授权 UTL_FILE的错误:
切换到sysdba: connect sys/XXX as sysdba; XXX表示Oracle DBA用户的密码
给当前用户授权UTL_FILE:grant execute on utl_file to 当前用户;
二、在执行过程时,execute read_file('D: emp','abc.txt'); 常见的错误有 'invalid directory path'。原因:11g以后建议使用directory变量替换utl_file第一个参数,这时写具体的路径会提示无效路径,因此,需要定义一个directory变量,代替D: emp,具体做法如下:
创建directory变量:create or replace directory D_DIR as 'D: emp'; [我的电脑,正反斜杠都可以]
如果上面的directory变量 是在当前用户下定义的则以,否则如果是在SYSDBA下定义的,也需要给使用的用户授权,如下:
给当前用户授权directory变量 :grant read,write on directory D_DIR to 当前用户; 【D_DIR、当前用户, -------》 都必须大写】
三、最后执行上面的过程:
execute read_file('D_DIR','abc.txt');
扩展:
查看当前用户被授权的内容:select * from dba_tab_privs where grantee = '当前用户';
授权:grant read,write on directory D_DIR to '当前用户';
取消授权:revoke read,write on directory D_DIR from '当前用户';