.comment-link {margin-left:.6em;}

Thursday, May 05, 2005

Movendo Arquivos Com PL/SQL

Mover arquivos no sistema operacional usando pl/sql. O ambiente que usei para prova foi Unix com a versão 9i. E do Unix que ocorreu essa idéia, rename no unix é mv (mover), então usei a utl_file.frename para "mover" o arquivo.

No exemplo a procedure create_file recebe dois parâmetros: diretório e nome do arquivo e, literalmente cria e joga 10 linhas dentro do arquivo. Depois faço uma busca para encontrar o arquivo na origem e destino, um pequeno bloco pl/sql anônimo para mover o arquivo e novamente o teste da existência dos arquivos.


ops$mportes@FCCUAT9I> create or replace
2 procedure create_file( p_name varchar2, p_dir varchar2 )
3 is
4 l_output utl_file.file_type;
5 begin
6 l_output := utl_file.fopen( p_dir, p_name, 'w' );
7 for x in 1 .. 10
8 loop
9 utl_file.put_line( l_output, 'Linha ' || x );
10 end loop;
11 utl_file.fclose(l_output);
12 end;
13 /

Procedure created.

ops$mportes@FCCUAT9I> show error
No errors.
ops$mportes@FCCUAT9I>
ops$mportes@FCCUAT9I> exec create_file( 'x.dummy', '/home01/mportes/tmp' )

PL/SQL procedure successfully completed.

ops$mportes@FCCUAT9I>
ops$mportes@FCCUAT9I> !ls -l /home01/mportes/tmp/x*
-rw-rw-r-- 1 oracle dba 81 May 5 10:51 /home01/mportes/tmp/x.dummy

ops$mportes@FCCUAT9I> !ls -l /home01/mportes/samples/x*
/home01/mportes/samples/x* not found

ops$mportes@FCCUAT9I>
ops$mportes@FCCUAT9I> begin
2 utl_file.frename (
3 src_location => '/home01/mportes/tmp',
4 src_filename => 'x.dummy',
5 dest_location => '/home01/mportes/samples',
6 dest_filename => 'x.dummy' );
7 end;
8 /

PL/SQL procedure successfully completed.

ops$mportes@FCCUAT9I>
ops$mportes@FCCUAT9I> !ls -l /home01/mportes/tmp/x*
/home01/mportes/tmp/x* not found

ops$mportes@FCCUAT9I> !ls -l /home01/mportes/samples/x*
-rw-rw-r-- 1 oracle dba 81 May 5 10:51 /home01/mportes/samples/x.dummy

ops$mportes@FCCUAT9I>


Abraços,

[Adendo ao artigo em 09/Maio/2005]
Recebi dois comentários sobre este artigo. O primeiro de um colega de trabalho, que me alertou de uma omissão: Eu havia esquecido de mencionar o parâmetro utl_file_dir. Sem que o mesmo esteja configurado o exemplo acima não funciona.

E outro, foi o do Vander, que está aqui no site, querendo ver um exemplo no Windows. Então vamos ao exemplo. Basicamente, eu verifiquei meu utl_file_dir, para saber onde ia apontar meu arquivo e mudei os comandos de sistema operacional.


ops$marcio@ORA10G> show parameter utl_file_dir

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
utl_file_dir string C:\oracle\oradata\ora10g\UTL_F
ILE_DIR
ops$marcio@ORA10G> create or replace
2 procedure create_file( p_name varchar2, p_dir varchar2 )
3 is
4 l_output utl_file.file_type;
5 begin
6 l_output := utl_file.fopen( p_dir, p_name, 'w' );
7 for x in 1 .. 10
8 loop
9 utl_file.put_line( l_output, 'Linha ' || x );
10 end loop;
11 utl_file.fclose(l_output);
12 end;
13 /

Procedure created.

ops$marcio@ORA10G>
ops$marcio@ORA10G> show error
No errors.
ops$marcio@ORA10G> exec create_file( 'x.dummy', 'C:\oracle\oradata\ora10g\UTL_FILE_DIR' )

PL/SQL procedure successfully completed.

ops$marcio@ORA10G>
ops$marcio@ORA10G> host dir C:\oracle\oradata\ora10g\UTL_FILE_DIR\x*
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\oracle\oradata\ora10g\UTL_FILE_DIR

05/09/2005 02:09 AM 91 x.dummy
1 File(s) 91 bytes
0 Dir(s) 1,224,814,592 bytes free

ops$marcio@ORA10G> host dir C:\oracle\oradata\ora10g\UTL_FILE_DIR\z*
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\oracle\oradata\ora10g\UTL_FILE_DIR

File Not Found

ops$marcio@ORA10G>
ops$marcio@ORA10G> begin
2 utl_file.frename (
3 src_location => 'C:\oracle\oradata\ora10g\UTL_FILE_DIR',
4 src_filename => 'x.dummy',
5 dest_location => 'C:\oracle\oradata\ora10g\UTL_FILE_DIR',
6 dest_filename => 'Z.dummy' );
7 end;
8 /

PL/SQL procedure successfully completed.

ops$marcio@ORA10G>
ops$marcio@ORA10G> host dir C:\oracle\oradata\ora10g\UTL_FILE_DIR\x*
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\oracle\oradata\ora10g\UTL_FILE_DIR

File Not Found

ops$marcio@ORA10G> host dir C:\oracle\oradata\ora10g\UTL_FILE_DIR\z*
Volume in drive C has no label.
Volume Serial Number is 4064-FF3B

Directory of C:\oracle\oradata\ora10g\UTL_FILE_DIR

05/09/2005 02:09 AM 91 Z.dummy
1 File(s) 91 bytes
0 Dir(s) 1,224,814,592 bytes free

Comments:
Márcio,

Qual a diferença de fazer isso no ambiente Unix e no ambiente Windows ??? tenho muita mudança de comandos ??? essas coisas. No Unix legal, funciona blz, mas e no Windows, fiquei com essa dúvida.
 
Tá lá seu exemplo Vander!
abraço!
 
Marcio,

Legal seu exemplo. Acredito que com o uso de DIRECTORY deve funcionar melhor, haja visto que o parâmetro UTL_FILE_DIR se não me engano é um parâmero de INIT, e o DIRECTORY pode ser alterado sem a necessidade de parar o banco.
Quanto ao Windows, vale ressaltar que se o diretório destino for outra máquina, o serviço do Oracle não pode rodar como Local Service. Deve-se destinar um usuário em um domínio, e delegar direito no diretório destino a esse usuário.

[ ]´s
 
Sim, boa idéia -- usando o DIRECTORY fica mais flexível mesmo, dependendo do como sua aplicação fará uso disso.

Quando ao Windows, muito complicado para ir nesse nível domain/user -- ao menos para mim, eu não faria. Por isso mesmo sou usuário e fã do Unix.

abs,
 
Márcio,

Estou com uma necessidade um pouco parecida com o exemplo que mostrou. Porém eu preciso executar o comando pelo pl/sql, ou seja, sem o uso do prompt. Tem alguma idéia?

[ ]'s
 
é só usá-lo dentro do seu pl/sql. A utl_file.frename é uma procedure dentro de uma package, só usar.
Caso não haja grant, peça a seu DBA para dar grant execute na utl_file para seu usuário.
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?