Usuário com melhor resposta
SQL Server - Lendo e (re)gravando TXT com quebra de linha

Pergunta
-
Teoricamente simples, mas estou apanhando! =(
Quero simplesmente ler um arquivo "entradas.txt" que tem o código CHR(10) como quebra de linha e gravar outro arquivo "saidas.txt" incluindo o CHR(13) antes do CHR(10)...
Não precisa tabela nem nada! Apenas ler e reescrever. Único detalhe é o tamanho do arquivo TXT que tem mais de 2 Gb e mais de 54 milhões de linhas.
Pode não parecer tão grande, mas o código para a mesma solução em VBA (MS Excel) esbarrou numa variável interna LOC que é do tipo LONG e o TXT extrapolou os 2.147.483.647 pra esse tipo de variável... daí não lê mais!Grato!
Respostas
-
Bom dia,
Se eu entendi bem, vc quer ler um arquivo txt, jogar esse conteúdo em uma variável e reescrever ??? É isso ?
O SQL não tem um recurso onde vc possa interar como o foreach !!! Vc vai precisar de uma tabela para fazer isso, nem que seja uma temporária !!!! Não tem como fugir !!!
Qual o modelo dos dados desse arquivo ?
Um exemplo é:
CREATE TABLE [dbo].[TABELADESTINO]( [Coluna 0] bigint NULL, [Coluna 1] bigint NULL, [Coluna 2] bigint NULL, [Coluna 3] datetime NULL, [Coluna 4] varchar(10) NULL, [Coluna 5] varchar(500) NULL, [Coluna 6] varchar(1) NULL ) BULK INSERT TABELADESTINO FROM 'C:\Users\flavio\Desktop\TECHNET.txt' WITH ( FIELDTERMINATOR = ';', ROWTERMINATOR = '\n' )
Para conhecer mais sobre Bulk Insert, clique aqui !
E para conhecer mais sobre terminadores de campo e linha, clique aqui !
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
- Editado Flávio Augusto Lacerda de FariasMVP sexta-feira, 6 de novembro de 2015 10:23
- Marcado como Resposta MLRamos sexta-feira, 6 de novembro de 2015 11:45
Todas as Respostas
-
Bom dia,
Se eu entendi bem, vc quer ler um arquivo txt, jogar esse conteúdo em uma variável e reescrever ??? É isso ?
O SQL não tem um recurso onde vc possa interar como o foreach !!! Vc vai precisar de uma tabela para fazer isso, nem que seja uma temporária !!!! Não tem como fugir !!!
Qual o modelo dos dados desse arquivo ?
Um exemplo é:
CREATE TABLE [dbo].[TABELADESTINO]( [Coluna 0] bigint NULL, [Coluna 1] bigint NULL, [Coluna 2] bigint NULL, [Coluna 3] datetime NULL, [Coluna 4] varchar(10) NULL, [Coluna 5] varchar(500) NULL, [Coluna 6] varchar(1) NULL ) BULK INSERT TABELADESTINO FROM 'C:\Users\flavio\Desktop\TECHNET.txt' WITH ( FIELDTERMINATOR = ';', ROWTERMINATOR = '\n' )
Para conhecer mais sobre Bulk Insert, clique aqui !
E para conhecer mais sobre terminadores de campo e linha, clique aqui !
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
- Editado Flávio Augusto Lacerda de FariasMVP sexta-feira, 6 de novembro de 2015 10:23
- Marcado como Resposta MLRamos sexta-feira, 6 de novembro de 2015 11:45
-
É isso mesmo Flávio.
Uma das minhas primeiras dúvidas era justamente da obrigatoriedade (ou não) em utilizar uma tabela (temporária) para esse fim... ! =(
Era um dos itens que eu queria fugir... mas supondo que eu utilize o código fornecido e gere uma tabela temporária minha outra dúvida é: um simples SELECT * from TEMPORARIA irá gerar um resultado na mesma ORDEM de leitura feito pelo BULK INSERT ?
-
MLRamos,
Você poderia através das ferramentas de Importação/Exportação de dados do SQL Server realizar o acesso, leitura e importação do conteúdo deste arquivo .txt para uma nova tabela em seu banco de dados, fazendo com que esta tabela seja justamente criada de acordo com a estrutura do seu arquivo.
Outra possibilidade seria utilizar os comandos SQLCMD ou BCP.
Pedro Antonio Galvao Junior [MVP | MCC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | Professor Universitario | SoroCodigos | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]
-
Já ouviram aquela expressão "O bom é inimigo do ótimo!" ? =)
Estou partindo para RESOLVER e criei o seguinte código:
USE TESTE
DECLARE @retorno INT
/*
CREATE TABLE [dbo].[TEMPOR](
LINHA VARCHAR(999)
)
*/
TRUNCATE TABLE TEMPOR
EXEC @retorno = MASTER..xp_cmdshell 'dir C:\@IMPORTA\TESTE\TEMPOR.txt'
IF @retorno = 0
BULK INSERT dbo.TEMPOR -- inserir na tabela desejada
FROM 'C:\@IMPORTA\TESTE\TEMPOR.txt'-- caminho do arquivo e formato
WITH
(
ROWTERMINATOR = '\\'
)
Resumindo, criei uma tabela TEMPOR num banco TESTE com apenas 1 coluna: LINHA! Mais simples impossível (acho).
Acontece que o ROWTERMINATOR não é reconhecido ... =(
Li o link fornecido pelo Flavio sobre terminadores de linha, mas o chr(10) aparentemente não é reconhecido...
=(
-
-
-
Se eu copiasse o conteúdo aqui não ficariam os caracteres não imprimíveis de fim de linha, etc...
Consegui!
DECLARE @bulk_cmd varchar(1000);
SET @bulk_cmd = 'BULK INSERT dbo.TEMPOR
FROM ''C:\@IMPORTA\TESTE\TEMPOR.txt''
WITH (ROWTERMINATOR = '''+CHAR(10)+''')';
EXEC(@bulk_cmd);
Obrigado!
-
Já ouviram aquela expressão "O bom é inimigo do ótimo!" ? =)
Estou partindo para RESOLVER e criei o seguinte código:
USE TESTE
DECLARE @retorno INT
/*
CREATE TABLE [dbo].[TEMPOR](
LINHA VARCHAR(999)
)
*/
TRUNCATE TABLE TEMPOR
EXEC @retorno = MASTER..xp_cmdshell 'dir C:\@IMPORTA\TESTE\TEMPOR.txt'
IF @retorno = 0
BULK INSERT dbo.TEMPOR -- inserir na tabela desejada
FROM 'C:\@IMPORTA\TESTE\TEMPOR.txt'-- caminho do arquivo e formato
WITH
(
ROWTERMINATOR = '\\'
)
Resumindo, criei uma tabela TEMPOR num banco TESTE com apenas 1 coluna: LINHA! Mais simples impossível (acho).
Acontece que o ROWTERMINATOR não é reconhecido ... =(
Li o link fornecido pelo Flavio sobre terminadores de linha, mas o chr(10) aparentemente não é reconhecido...
=(
Outra coisa, \\ é diferente de Char(10)....
Char(10) é Line Feed..... o que nesse exemplo é o \n e o Char(13) seria o \r.
Vc tentou fazer usando a ferramenta de importação do SQL, conforme a dica do Pedro ?
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
-
Flavio voce deve ter visto minha resposta depois, certo ? =)
Funcionou... Quase... =(
A parte que funcionou é a carga completa do arquivo TEMPOR.txt !
Mas um simples SELECT * FROM TEMPOR está retornando erro:
Erro ao executar o lote. Mensagem de erro: Exceção do tipo 'System.OutOfMemoryException' foi acionada.
Num PC com 16Gb e 12Gb já configurados no SQL Server 2012 de 64 bits...
Pelo que eu li, a respeito o comentário é falta de memória... !
=(
-
Flavio voce deve ter visto minha resposta depois, certo ? =)
Funcionou... Quase... =(
A parte que funcionou é a carga completa do arquivo TEMPOR.txt !
Mas um simples SELECT * FROM TEMPOR está retornando erro:
Erro ao executar o lote. Mensagem de erro: Exceção do tipo 'System.OutOfMemoryException' foi acionada.
Num PC com 16Gb e 12Gb já configurados no SQL Server 2012 de 64 bits...
Pelo que eu li, a respeito o comentário é falta de memória... !
=(
Faça assim:
SELECT TOP 10 * FROM TEMPOR
Retorna ?
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
-
Se vc quiser retornar esse resultado, vc precisa alterar uma configuração !
Em ferramentas - Opções, vc tem que alterar o máximo de caracteres retornados !!
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
-
-
É isso mesmo Flávio.
Uma das minhas primeiras dúvidas era justamente da obrigatoriedade (ou não) em utilizar uma tabela (temporária) para esse fim... ! =(
Era um dos itens que eu queria fugir... mas supondo que eu utilize o código fornecido e gere uma tabela temporária minha outra dúvida é: um simples SELECT * from TEMPORARIA irá gerar um resultado na mesma ORDEM de leitura feito pelo BULK INSERT ?
Funcionou !!!
Fica somente a dúvida: o SELECT na tabela TEMPORARIA traz os resultados na mesma ordem de leitura ?
=O
-
Quando vc faz o select e coloca em grade, ele tem que jogar o resultado em memória para depois exibir, por isso o erro !!!
Dai vc muda o valor de caracteres recuperados para um valor maior e ai vc conseguiria retornar o resultado do seu select em grade, quando vc muda para exibir em arquivo não dá erro, por que ele cria um temporário em disco !
O select na tabela temporária sem nenhuma ordem, vai trazer os registros por ordem de inserção, a principio na mesma ordem de leitura feita pelo Bulk Insert !!!
Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
-
Flavio,
Executei um primeiro período e funcionou 100%!
Agora, no segundo, um SELECT * FROM TEMPOR está gerando em outra ordem que não é a de leitura, feita pelo BULK INSERT! =(
Estou zerando a tabela entre um período e outro fazendo um TRUNCATE TABLE, depois executo o BULK INSERT e por último o SELECT ...
Alguma sugestão?