Importação de SQL em massa do CSV

Eu preciso importar um arquivo CSV grande em um servidor SQL. Eu estou usando isso:

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

problema é que todos os meus campos estão rodeados por aspas (""), então uma linha realmente se parece com:

"1","","2","","sometimes with comma , inside", "" 

Posso de alguma forma importá-los em massa e dizer ao SQL para usar as aspas como delimitadores de campo?

Edit: The problem with using '","' as delimiter, as in the examples suggested is that : What most examples do, is they import the data including the first " in the first column and the last " in the last, then they go ahead and strip that out. Alas my first (and last) column are datetime and will not allow a "20080902 to be imported as datetime.

Pelo que tenho lido, acho que o FORMATFILE é o caminho a percorrer, mas a documentação (incluindo o MSDN) é terrivelmente inútil.

0
adicionado editado
Visualizações: 1
Você deve marcar novamente este sqlserver para sabermos qual banco de dados você está usando.
adicionado o autor JasonS, fonte

12 Respostas

Você tem que tomar cuidado com o BCP/BULK INSERT, pois nem o BSP nem o Bulk Insert lidam bem com isso se a citação não for consistente, mesmo com arquivos formatados (mesmo arquivos com formato xml não oferecem a opção) e caracteres fictícios no começo e fim e usando [","] como o separador. Tecnicamente, os arquivos CSV não precisam ter ["] caracteres se não houver caracteres [] incorporados

É por esse motivo que os arquivos delimitados por vírgulas são às vezes chamados de arquivos limitados por comédia.

O OpenRowSet exigirá o Excel no servidor e pode ser problemático em ambientes de 64 bits - eu sei que é problemático usar o Excel no Jet em 64 bits.

SSIS é realmente a sua melhor aposta se o arquivo é susceptível de variar a partir de suas expectativas no futuro.

0
adicionado

Yup, K Richard is right: FIELDTERMINATOR = '","'

Veja http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file para mais informações.

0
adicionado

Experimente o OpenRowSet . Isso pode ser usado para importar itens do Excel. Excel pode abrir arquivos CSV, então você só precisa descobrir o correto [ConnectionString] [2].

[2]: Driver = {Driver de Texto da Microsoft (* .txt; * .csv)}; Dbq = c: \ txtFilesFolder \; Extensões = asc, csv, tab, txt;

0
adicionado

Outro hack que eu às vezes uso, é abrir o CSV no Excel e, em seguida, gravar sua instrução sql em uma célula no final de cada linha. Por exemplo:

=concatenate("insert into myTable (columnA,columnB) values ('",a1,"','",b1,"'")")

Um preenchimento pode preencher isso em cada linha para você. Em seguida, basta copiar e colar a saída em uma nova janela de consulta.

É old-school, mas se você só precisa fazer importações de vez em quando, você evita a leitura de toda a documentação obscura da maneira "correta" de fazê-lo.

0
adicionado
Boa dica, @jorgeburgos
adicionado o autor karlgrz, fonte
Eu sei que essa resposta é antiga, mas acabei de chegar aqui com uma pesquisa no Google por algo parecido. É ótimo você querer gerar qualquer código a partir de dados tabulares, não apenas codificar para carregar uma instrução SQL. Você pode colocar um modelo em algum lugar no arquivo do Excel, então faça = SUBSTITUTE ($ Z $ 999, "placeholder_a", "'" & SUBSTITUTE (A2, "'", "''") & "'"), "placeholder_b", SUBSTITUTE (B2, "'", "' '")) . Supondo que você tenha um modelo em $ Z $ 999.
adicionado o autor Don 01001100, fonte
Boa dica, obrigado!
adicionado o autor DanB, fonte

Você precisa fazer isso programaticamente, ou é uma chance única?

Usando o Enterprise Manager, clique com o botão direito do mouse em Importar dados para selecionar seu delimitador.

0
adicionado

Se você descobrir como obter o arquivo analisado em um DataTable, sugiro a classe SqlBulkInsert para inseri-lo no SQL Server.

0
adicionado

Você também pode usar o DTS ou o SSIS.

0
adicionado

Try FIELDTERMINATOR='","'

Aqui está um ótimo link para ajudar com a primeira e última cotação ... olha como ele usou a substring do SP

http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file

0
adicionado
Trabalhei para mim também. Eu estou usando um arquivo de formato xml para que o atributo Terminator foi usado em vez de FIELDTERMINATOR. Além disso, na minha última coluna, usei o seguinte TERMINATOR = '"\ r \ n'
adicionado o autor Craig McKeachie, fonte
Não funcionará :-(. O primeiro campo na tabela é um datetime e irá importar a aspas inicial (") com ele, gerando um erro
adicionado o autor Radu094, fonte
Também tome cuidado com aplicativos que exportam CSV com strings citadas, mas números não citados.
adicionado o autor finnw, fonte

Você tem controle sobre o formato de entrada? | (pipes), e geralmente fazem melhores terminadores de campo.

0
adicionado

Eu sei que isso não é uma solução real, mas eu uso uma tabela fictícia para a importação com nvarchar definido para tudo. Então eu faço uma inserção que retira os "personagens e faz as conversões. Não é bonito, mas faz o trabalho.

0
adicionado
Como você divide os campos quando pode haver vírgulas entre aspas?
adicionado o autor Jeremy Stein, fonte

Eu digo que usar FileHelpers é uma biblioteca de código aberto

0
adicionado

Firs, você precisa importar o arquivo CSV para a tabela de dados

Em seguida, você pode inserir linhas em massa usando o SQLBulkCopy

using System;
using System.Data;
using System.Data.SqlClient;

namespace SqlBulkInsertExample
{
    class Program
    {
      static void Main(string[] args)
        {
            DataTable prodSalesData = new DataTable("ProductSalesData");

           //Create Column 1: SaleDate
            DataColumn dateColumn = new DataColumn();
            dateColumn.DataType = Type.GetType("System.DateTime");
            dateColumn.ColumnName = "SaleDate";

           //Create Column 2: ProductName
            DataColumn productNameColumn = new DataColumn();
            productNameColumn.ColumnName = "ProductName";

           //Create Column 3: TotalSales
            DataColumn totalSalesColumn = new DataColumn();
            totalSalesColumn.DataType = Type.GetType("System.Int32");
            totalSalesColumn.ColumnName = "TotalSales";

           //Add the columns to the ProductSalesData DataTable
            prodSalesData.Columns.Add(dateColumn);
            prodSalesData.Columns.Add(productNameColumn);
            prodSalesData.Columns.Add(totalSalesColumn);

           //Let's populate the datatable with our stats.
           //You can add as many rows as you want here!

           //Create a new row
            DataRow dailyProductSalesRow = prodSalesData.NewRow();
            dailyProductSalesRow["SaleDate"] = DateTime.Now.Date;
            dailyProductSalesRow["ProductName"] = "Nike";
            dailyProductSalesRow["TotalSales"] = 10;

           //Add the row to the ProductSalesData DataTable
            prodSalesData.Rows.Add(dailyProductSalesRow);

           //Copy the DataTable to SQL Server using SqlBulkCopy
            using (SqlConnection dbConnection = new SqlConnection("Data Source=ProductHost;Initial Catalog=dbProduct;Integrated Security=SSPI;Connection Timeout=60;Min Pool Size=2;Max Pool Size=20;"))
            {
                dbConnection.Open();
                using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
                {
                    s.DestinationTableName = prodSalesData.TableName;

                    foreach (var column in prodSalesData.Columns)
                        s.ColumnMappings.Add(column.ToString(), column.ToString());

                    s.WriteToServer(prodSalesData);
                }
            }
        }
    }
}
0
adicionado