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.
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.
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:
<< Home
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.
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.
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
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,
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
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
Caso não haja grant, peça a seu DBA para dar grant execute na utl_file para seu usuário.
<< Home