#13 XP_CMDSHELL - parte 2
Autor: Bruno Martins | Publicado: 2011-05-26T10:48:00-03:00

Essa postagem não é minha foi retirada do fórum do iMasters (http://forum.imasters.com.br/topic/224741-xp-cmdshell/) pelo&nbsp;eriva_br&nbsp;(http://forum.imasters.com.br/user/16361-eriva-br/), achei muito boa e estou colocando aqui para compartilhar e colocando todos os links da fonte do post.


Caracteristicas:
Nome: XP_CMDSHELL
Localização: Banco de dados Master
Tipo: Extended Procedure
Descrição: Esta procedure executa uma sequencia de comandos em string do tipo shell no computador onde o sql server está instalado.
Utilidades: listar diretórios; criar, copiar, apagar arquivos; enviar mensagens, etc

Parâmetros:
'command_string', obrigatório, é o comando a ser executado
no_output, opcional, se colocado indica que não será retornado mensagem de saída na execução

Retornos:
retona 0 ou 1: 0-sucesso ou 1-Falha

Observações:
Obs1.: esta proc trabalha de forma&nbsp;sincrona, os comandos colocados abaixo dela só serão executados após o término de sua execução, ao contrário do comando shell do vb6 que trabalha de forma assincrona, ao ser executado, mesmo sem ter finalizado o comando já é liberado para a linha subsequente.
Obs2.: verificar segurança, tomar cuidados com SQL Injection, dica do nosso amigo&nbsp;Micox
http://www.macoratti.net/sql_inj.htm
http://www.google.com.br/search?hl=pt-BR&amp;a...ta=lr%3Dlang_pt

Exemplos de uso:
exemplo 1: copiando um arquivo
declare @retorno INT
&nbsp; EXEC @retorno = MASTER..xp_cmdshell 'copy C:\Lixo\teste.txt C:\Lixo\testeBKP.txt'
&nbsp; select CASE WHEN @retorno = 0 THEN 'COPIADO COM SUCESSO' ELSE 'FALHA NO COMANDO' END as Retorno

exemplo 2: listando os arquivos de uma pasta
declare @retorno int
&nbsp; EXEC @retorno = master..xp_cmdshell 'dir C:\lixo\'
&nbsp; if @retorno = 0
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print 'comando executado com EXITO'
&nbsp; else
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print 'FALHA no comando'
para testar esse exemplo verificando uma execução com sucesso e uma com falha, teste passando o caminho correto do arquivo e depois teste definindo o caminho incorretamente


exemplo 3: deletando um arquivo
EXEC MASTER..XP_CMDSHELL 'del C:\Lixo\teste.txt'

exemplo 4: enviando mensagens
EXEC master..xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server será desligado em em 1 minuto.'

exemplo 5: escrevendo em um arquivo texto
DECLARE @arqTexto VARCHAR(8000),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @caminho VARCHAR(255),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @retEcho INT --variavel para verificar se o comando foi executado com exito ou ocorreu alguma falha
&nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SET @caminho = 'C:\Lixo\teste.txt'
&nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SET @arqTexto = 'ECHO Registro;CAMPO1;CAMPO2;CAMPO3 ' + CONVERT(VARCHAR(30),GETDATE()) + &nbsp;' &gt;&gt; ' + @caminho
&nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --remove caracteres não aceitos pelo comando ECHO, veja no final do post comentário
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select @arqTexto = dbo.FU_CONVERTE_TXT(@arqTexto)
&nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --escreve no arquivo txt, se ele naum existir será criado, se existir será adicionado (incrementado) a partir da última linha
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EXEC @retEcho = MASTER..XP_CMDSHELL @arqTexto, NO_OUTPUT --NO_OUTPUT indica que o comando não irá retornar alguma possível mensagem na sua execução
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IF (@retEcho &lt;&gt; 0)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BEGIN
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --caso ocorrer algum erro podemos retornar uma mensagem
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT 'ocorreu erro, verifique se o diretório existe' as Falha, @retEcho as retEcho
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END


exemplo 6: escrevendo arquivo texto, vamos escrever um arquivo texto com alguns campos da tabela authors do banco de dados pubs, através de um loop
--definindo o banco pubs
&nbsp; use pubs;
&nbsp; --definindo variaveis
&nbsp; declare @arqTexto varchar(8000),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @au_fname varchar(50),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @au_lname varchar(50),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @caminho varchar(255),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @au_id varchar(20),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @retEcho INT --variavel para verificar se o comando foi executado com exito ou ocorreu alguma falha
&nbsp; 
&nbsp; --definindo o caminho e arquivo que será escrito, OBS: este caminho deve ser no servidor onde estiver instalado o SQL Server
&nbsp; set @caminho = 'C:\Lixo\teste.txt'
&nbsp; --setando o menor id para verificação do loop
&nbsp; select @au_id = min(au_id) from authors
&nbsp; --while da tabela authors
&nbsp; while @au_id is not null
&nbsp; begin
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --buscando os valores dos campos e adicionando nas variaveis
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select @au_id = au_id, @au_lname = au_lname, @au_fname = au_fname from authors
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where au_id = @au_id
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --setando o menor id para verificação do loop
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select @au_id = min(au_id) from authors
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where au_id &gt; @au_id
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --definindo a linha que será escrita no arquivo txt
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SET @arqTexto = 'ECHO Registro;' + @au_id + ';' + @au_lname + ';' + @au_fname + &nbsp;' &gt;&gt; ' + @caminho
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --escreve no arquivo txt, se ele naum existir será criado, se existir será adicionado (incrementado) a partir da última linha
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exec @retEcho = MASTER..XP_CMDSHELL @arqTexto
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IF (@retEcho &lt;&gt; 0)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BEGIN
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --caso ocorrer algum erro podemos retornar uma mensagem
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select 'ocorreu erro, verifique se o diretório existe' as Falha, @retEcho as retEcho
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --parar o loop em caso de erro
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; END
&nbsp; end




Atenção:
Para escrever arquivo texto, cuidado com os caracteres especiais, pois se for um destes caracteres no comando a linha inteira não é escrita, dai imagina um arquivo texto de exportação faltando uma linha lá no meio do arquivo... como diria o Silvio Luiz, "o que que eu vou dizer lá no 'escritório'!"
Os caracteres que verifiquei até agora que não são aceitos pelo comando ECHO estão na função abaixo que fiz para trocar tais caracteres, se ver mais algum por favor nos avise:
CREATE FUNCTION FU_TRANSFORMA_CARACTERES (@Texto VARCHAR(8000))
&nbsp; RETURNS VARCHAR(8000)
&nbsp; AS
&nbsp; BEGIN
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Á','A'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Á','A'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ã','A'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Â','A'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ó','O'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ô','O'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Õ','O'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ú','U'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ü','U'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Í','I'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'É','E'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ê','E'))
&nbsp; SET @Texto = UPPER(REPLACE(@Texto,'Ç','C'))
&nbsp; SET @Texto = REPLACE(@Texto,'&amp;','e')
&nbsp; SET @Texto = REPLACE(@Texto,'"',' ')
&nbsp; 
&nbsp; RETURN @Texto
&nbsp; END


AUTOR: "eriva_br"

Dúvidas, criticas, contribuições, correções e adições seram bem vindas.