Pergunta

Eu tenho um despejo de CSV de outro banco de dados que se parece com este (id, nome, notas):

1001, John Smith, 15 Main Street
1002, Jane Smith, "2010 Rockliffe Dr.
Pleasantville, IL
EUA"
1003, Bill Karr, 2820 West Ave.

O último campo pode conter retornos e vírgulas do carro, caso em que é cercado por citações duplas. E eu preciso preservar esses retornos e vírgulas.

Eu uso este código para importar CSV para a minha tabela:

BULK INSERT CSVTest
FROM 'c:\csvfile.csv'
WITH
(
  FIELDTERMINATOR = ',',
  ROWTERMINATOR = '\n'
)

SQL Server 2005 A inserção em massa não consegue descobrir que os retornos de carruagem dentro de citações não são terminadores de linha.
Como superar?


ATUALIZAR:
Parece que a única maneira de manter quebras de linha dentro de um campo é usar o separador de linhas diferentes. Então, eu quero marcar todas as quebras de linha separando a linha colocando um cano na frente deles. Como posso mudar meu CSV para ficar assim?

1001, John Smith, 15 Main Street |
1002, Jane Smith, "2010 Rockliffe Dr.
Pleasantville, IL
EUA "|
1003, Bill Karr, 2820 West Ave. |

Foi útil?

Solução 6

Ok, aqui está um pequeno programa Java que eu acabo escrevendo para resolver o problema.
Comentários, correções e otimizações são bem -vindos.

import java.io.*;

public class PreBulkInsert
{
    public static void main(String[] args)
    {
        if (args.length < 3)
        {
            System.out.println ("Usage:");
            System.out.println ("  java PreBulkInsert input_file output_file separator_character");
            System.exit(0);
        }

        try
        {
            boolean firstQuoteFound = false;
            int fromIndex;
            int lineCounter = 0;
            String str;

            BufferedReader in = new BufferedReader(new FileReader(args[0]));
            BufferedWriter out = new BufferedWriter(new FileWriter(args[1])); 
            String newRowSeparator = args[2];

            while ((str = in.readLine()) != null)
            {
                fromIndex = -1;
                do
                {
                    fromIndex = str.indexOf('"', fromIndex + 1);
                    if (fromIndex > -1)
                        firstQuoteFound = !firstQuoteFound;
                } while (fromIndex > -1);

                if (!firstQuoteFound)
                    out.write(str + newRowSeparator + "\r\n");
                else
                    out.write(str + "\r\n");
                lineCounter++;
            }
            out.close();
            in.close();
            System.out.println("Done! Total of " + lineCounter + " lines were processed.");
        }
        catch (IOException e)
        {
            System.out.println(e.getMessage());
            System.exit(1);
        }       
    }
}

Outras dicas

As operações em massa no SQL Server não suportam especificamente o CSV, mesmo que possam importá -las se os arquivos forem cuidadosamente formatados. Minha sugestão seria incluir todos os valores de campo nas cotações. A inserção em massa pode então permitir que o retorno do carro em um valor de campo. Caso contrário, sua próxima solução pode ser um pacote de serviços de integração.

Ver Preparando dados para exportação ou importação em massa para mais.

Você pode massagear essas quebras de linha em uma linha com um script, por exemplo, você pode usar o GNU sed Para remover quebras de linha. por exemplo

$ more file
1001,John Smith,15 Main Street
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"
1003,Bill Karr,"2820
West Ave"

$ sed '/"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ }' file
1001,John Smith,15 Main Street|
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"|
1003,Bill Karr,"2820
West Ave"|

Então você pode entrar em massa.

Editar:

Guarde isso :/"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ } Em um arquivo, digamos myformat.sed. Então faça isso na linha de comando

c:\test> sed.exe -f myformat.sed myfile

Você não pode importar isso, a menos que o CSV esteja em formato válido. Portanto, você deve corrigir o despejo ou usar manualmente a pesquisa e substituir, corrige os caracteres de nova linha indesejados.

De acordo com a fonte de todo o conhecimento (Wikipedia), CSV usa novas linhas para separar registros. Então, o que você tem não é CSV válido.

Minha sugestão é que você escreva um programa PERL para processar seu arquivo e adicionar cada registro ao banco de dados.

Se você não é uma pessoa Perl, pode usar um site de programação ou ver se algum tipo de pessoa escreverá a seção Parsing do programa para você.

Adicionado:

Solução possível

Como o OP afirma que ele pode alterar o arquivo de entrada, eu alteraria todas as novas linhas que não seguem um "para ser uma sequência de char reservada, por exemplo, xxx

Isso pode ser uma substituição automatizada em muitos editores. No Windows, o UltraEdit inclui a funcionalidade REGEXP Find/Substituir

Em seguida, importe para o DBMS, pois você não terá mais as novas linhas incorporadas.

Em seguida, use SQL Substituir Para alterar as ocorrências XXX de volta para novas linhas.

Se você tiver controle sobre o conteúdo do arquivo CSV, poderá substituir as quebras de linha em campo (CRLF) com um caráter não-linebreak (talvez apenas CR ou LF), em seguida, execute um script após a importação para substituí -los por CRLF novamente.

É assim que os produtos do MS Office (Excel, Access) lidam com esse problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top