Olá! Seja bem-vindo!

Integrar dados de um sistema para outro é uma tarefa corriqueira para DBAs e desenvolvedores.

Mais dia menos dia, chegará um momento onde você precisará importar arquivos do Windows para o banco de dados SQL, ou exportar arquivos do banco de dados SQL para o Windows.

No vídeo de hoje veremos como importar e exportar arquivos em massa para tabelas do SQL com apenas 2 scripts genéricos e bastante simples de utilizar no seu ambiente.

Assista aqui ao vídeo de demonstração:

Assista o vídeo de demonstração aqui:

IMPORTANDO ARQUIVOS PARA TABELAS DO SQL

Aqui no blog, já havíamos visto Como Salvar Imagens no SQL Server, porém, na ocasião, utilizamos o comando OPENROWSET em um script estático / hard coded.

No vídeo de hoje, vimos como utilizar o mesmo comando OPENROWSET de forma dinâmica, de maneira que você precisa apenas alterar a pasta onde estão seus arquivos e ele (o script) importará a todos de forma automatizada.

Um ponto de atenção: Antes de executar a importação, é fundamental verificar os pré-requisitos:

1) Confirmar que a máquina do SQL tem acesso de rede a máquina onde estão os arquivos a serem importados;

2) Confirmar que o usuário do serviço do SQL tem acesso a pasta onde estão os arquivos a serem importados;

Você pode testar isso facilmente usando a procedure sys.xp_dirtree, que lista arquivos e pastas.

EXPORTANDO ARQUIVOS DO SQL PARA O WINDOWS

Como vimos no vídeo, exportar arquivos de tabelas do SQL para o seu Windows depende de um pré-requisito importante: Ativar a opção “ole automation procedures” usando a SP_CONFIGURE.

Feito isso, ai é barbada! Só definir a variável @pasta_destino com o caminho onde o script deverá exportar os arquivos usando o objeto “adodb.stream”, que é criado usando a procedure “sys.sp_oacreate”.

Script completo da aula

Baixe o script completo da aula de hoje aqui:


------------------------------------------------------------------
-- Importar e exportar arquivos <-> tabelas no SQL Server
------------------------------------------------------------------

--------------------------------------------------
-- Banco de testes
--------------------------------------------------
set nocount on
go
use master
go
drop database if exists curso
go
create database curso
go
create table curso.dbo.arquivos (
	nm varchar(100) primary key,
	doc varbinary(max) not null
)
go

--------------------------------------------------
-- Requisitos
--------------------------------------------------
/*
1) "Máquina do SQL" precisa ter acesso de rede na máquina onde está a "pasta de arquivos". 
Nesse exemplo, a pasta está no servidor SQL, então não temos dificuldades. 
Se a pasta estiver na rede, é preciso garantir que a "máquina do SQL" tenha conectividade com a "máquina onde estão os arquivos". 

2) "Usuário do serviço do SQL" precisa ter acesso na "pasta dos arquivos".
Nesse exemplo, o usuário do SQL é o padrão da instalação, que é administrador da máquina local onde estão os arquivos, então não temos dificuldades. 
Se a pasta estiver na rede, é preciso garantir que o usuário que roda o serviço do SQL tenha acesso a pasta/compartilhamento onde estão os arquivos. 
Para conferir o usuário que roda o serviço do SQL, acesse a console de serviços em: 
	Iniciar > Executar > digite "services.msc" e clique OK
	Procure pelo serviço do SQL e verifique a credencial de logon

-- Script simples para testar se o SQL tem acesso a pasta: 
-- Se o retorno for "vazio" ou ocorrerem erros como "acesso negado", você terá de ajustar o acesso antes de prosseguir
-- Exemplos:
execute sys.xp_dirtree '\\192.168.59.135\RIS', 1, 1 -- diretório existe, mas o usuário do MEU SQL NÃO tem acesso!
execute sys.xp_dirtree '\\192.168.59.135\Users', 1, 1 -- diretório existe na minha rede e meu SQL tem acesso!
execute sys.xp_dirtree 'c:\tmp\arquivos-originais\', 1, 1 -- diretório local existe e meu SQL tem acesso!
go

*/

--------------------------------------------------
-- Importar: Diretório => SQL
--------------------------------------------------
-- Define a pasta onde estão os arquivos (Conta do serviço do SQL precisa ter acesso de leitura!)
declare @pasta varchar(255) = 'c:\tmp\arquivos-originais\'

-- Lista arquivos da pasta
declare @arquivos table (item varchar(255), depth int, eharquivo bit)
insert into @arquivos execute sys.xp_dirtree @pasta, 1, 1 -- sys.xp_dirtree [diretorio], [nivel de subpasta], [listar arquivos]

-- Salva arquivos no SQL
declare @nm varchar(255)
declare @sql varchar(max)
declare @c cursor 
set @c = cursor for select item from @arquivos where eharquivo = 1
open @c
fetch next from @c into @nm
while @@fetch_status = 0
	begin
		-- Monta comando de inserção do arquivo na base, usando o método openrowset
		set @sql = 'insert into curso.dbo.arquivos (nm, doc) select ''' + @nm + ''', bulkcolumn from openrowset (bulk ''' + @pasta + @nm + ''', single_blob) doc'
		-- Mostra o comando que será executado nas mensagens de retorno e o executa
		print @sql
		execute (@sql)
		fetch next from @c into @nm
	end
go

-- Verificar arquivos importados:
select * from curso.dbo.arquivos
go


--------------------------------------------------
-- Exportar: SQL => Diretório
--------------------------------------------------
-- Requisitos:
execute sys.sp_configure 'show advanced options', 1
go
reconfigure
go
execute sys.sp_configure 'ole automation procedures', 1
go
reconfigure
go


-- Script de exportação:
-- Define pasta de destino para onde os arquivos serão exportados:
declare @pasta_destino varchar(255) = 'c:\tmp\arquivos-exportados-do-sql\'

-- Cria pasta caso não exista:
declare @existe int;
execute master.dbo.xp_fileexist @pasta_destino, @existe out; -- verifica se dir existe
if @existe = 0 execute master.sys.xp_create_subdir @pasta_destino; -- cria, caso não exista

-- Configura componente ADODB.STREAM, que será usado para escrever os dados binários da tabela em arquivos do windows
declare @id_objeto int; 
declare @ds_caminho varchar(100)
execute sys.sp_oacreate 'adodb.stream', @id_objeto output
execute sys.sp_oasetproperty @id_objeto , 'type', 1

-- Define um cursor para leitura da tabela registro a registro:
declare @c cursor; declare @nm varchar(100); declare @doc varbinary(max)
set @c = cursor for select nm, doc from curso.dbo.arquivos
open @c
fetch next from @c into @nm, @doc

-- Salva um arquivo no windows para cada linha da tabela
while @@fetch_status = 0
	begin
		set @ds_caminho = @pasta_destino + @nm
		execute sys.sp_oamethod @id_objeto, 'open'
		execute sys.sp_oamethod @id_objeto, 'write', null, @doc
		execute sys.sp_oamethod @id_objeto,'savetofile', null, @ds_caminho, 2
		execute sys.sp_oamethod @id_objeto,'close'
		fetch next from @c into @nm, @doc
	end

-- Finaliza o script desalocando o componente
execute sys.sp_oadestroy @id_objeto
go


Conclusão

Existem diversas formas e ferramentas para importar e exportar arquivos em massa para tabelas do SQL, inclusive o próprio SSIS “SQL Server Integration Services” pode fazer isso de forma robusta.

Ainda assim, nada mais simples e rápido do que dispormos de uma solução via script, principalmente se esse for genérico e servir para qualquer caso.

Particularmente gosto desse tipo de abordagem, pois permite agilidade especialmente em casos onde estamos resolvendo um incidente urgente.

Abraço do seu amigo Josué

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *