none
SQL Server - Lendo e (re)gravando TXT com quebra de linha RRS feed

  • 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!

     
    sexta-feira, 6 de novembro de 2015 10:06

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"


    sexta-feira, 6 de novembro de 2015 10:17

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"


    sexta-feira, 6 de novembro de 2015 10:17
  • É 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 ?

    sexta-feira, 6 de novembro de 2015 10:34
  • 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]

    sexta-feira, 6 de novembro de 2015 10:57
  • 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... 

    =(


    sexta-feira, 6 de novembro de 2015 11:08
  • Como disponibilizo um exemplo do arquivo TEMPOR.TXT ?

    =(

    sexta-feira, 6 de novembro de 2015 11:22
  • Por aqui vc não consegue, a não ser que copie uma parte do conteúdo !

    Flávio Farias "May the Force be with you" Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"

    sexta-feira, 6 de novembro de 2015 11:42
  • 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!

    sexta-feira, 6 de novembro de 2015 11:45
  • 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"

    sexta-feira, 6 de novembro de 2015 11:47
  • 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... !

    =(

    sexta-feira, 6 de novembro de 2015 12:50
  • 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"

    sexta-feira, 6 de novembro de 2015 13:41
  • 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"

    sexta-feira, 6 de novembro de 2015 14:06
  • Flavio ... minhas configurações estão iguais as que vc postou e em GRADE não deu resultados... 

    Mas não precisa !!! Funcionou para arquivo... 

    =) 

    Agora vou ver se ficou 100%

    sexta-feira, 6 de novembro de 2015 15:25
  • É 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

    sexta-feira, 6 de novembro de 2015 15:42
  • 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"

    sexta-feira, 6 de novembro de 2015 16:40
  • 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?

    segunda-feira, 9 de novembro de 2015 18:37