É possível select…into com bulk insert? Sim, com openrowset.

O título diz tudo.

Quando temos uma tabela exportada para um ficheiro com BCP, quando necessitamos de a importar usamos BULK INSERT.

Até aqui nada de novo.

Vamos ver a questão com um exemplo.

create table ToExport (
	id int identity(1,1)
,	col1 char(2)  
,	col2 bigint
)

insert into ToExport
	(col1, col2)
select 'AA', 123
from sys.objects a
cross join sys.objects b

No nosso caso, 10404 linhas.

Agora vamos fazer uma exportação para ficheiro.

exec xp_cmdshell ' bcp Demo01.dbo.ToExport out  C:\Files\ToExport.dat -c -S localhost\sql2019 -T '	

Pois… servidor novo, não me lembrei de configurar.

EXEC sp_configure 'show advanced options', 1;  
GO  
RECONFIGURE;  
GO  
EXEC sp_configure 'xp_cmdshell', 1;  
GO  
RECONFIGURE;  
GO 

Agora repetir a exportação.

exec xp_cmdshell ' bcp Demo01.dbo.ToExport out  C:\Files\ToExport.dat -c -S localhost\sql2019 -T '	

Agora sim.

Temos então um ficheiro com a nossa tabela exportada.

Agora queremos importar para outra tabela.

Quando temos acesso à definição da tabela tudo se torna simples.

create table ToImport (
	id int 
,	col1 char(2)  
,	col2 bigint
)

bulk insert ToImport
from 'C:\Files\ToExport.dat'
select top 10 *
from ToImport

Mas… e se precisassemos de fazer um select … into?

Sim, parece estranho, mas já me aconteceu.
Deram-me acesso num servidor para correr uma SP que exportava uma tabela, mas não tinha acesso à tabela nem conseguia fazer uma remote query com OPENROWSET.
Queria importar a tabela do ficheiro mas não sabia que colunas tinha.

Basicamente, tinha acesso a correr a SP para gerar o ficheiro.
Felizmente também tinha acesso à dita SP e podia editá-la.

Primeiro passo foi adicionar à SP a criação de um ficheiro de formato.

exec xp_cmdshell ' bcp Demo01.dbo.ToExport format nul -f C:\Files\ToExport.fmt -c -S localhost\sql2019 -T '	

Agora quando correr a SP ela cria-me dois ficheiros, o .dat com a tabela e o .fmt com a format file.

Com esses dois ficheiros posso agora dar o passo seguinte.

select a.*
into ToImport_Nova
from openrowset ( 
	bulk 'C:\Files\ToExport.dat', formatfile = 'C:\Files\ToExport.fmt'
) a
select top 10 *
from ToImport_Nova

E pelo menos já temos os nossos dados.

Mas será que correu tudo bem?

Vamos ver o que temos no nosso Object Explorer?

Está tudo parecido, não está?
Pois… não está.

Agora os campos são todos varchar. Não tenho nenhuma referência de como eles estão na tabela original.
Aqui sei porque tenho acesso às duas, mas neste caso real tinha feito um grande erro.

Vamos lá resolver isto

Criamos dois novos ficheiros, mas desta vez em “native data type”.
No fundo é tudo igual mas com -n em vez de -c.

exec xp_cmdshell ' bcp Demo01.dbo.ToExport out  C:\Files\ToExport_N.dat -n -S localhost\sql2019 -T '	
exec xp_cmdshell ' bcp Demo01.dbo.ToExport format nul -f C:\Files\ToExport_N.fmt -n -S localhost\sql2019 -T '	

Agora fazemos o mesmo mas usando os novos ficheiros.

select a.*
into ToImport_Nova_N
from openrowset ( 
	bulk 'C:\Files\ToExport_N.dat', formatfile = 'C:\Files\ToExport_N.fmt'
) a

Agora está melhor, ou não?

Share

You may also like...

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *