Utilizzare BCP per importare i file CSV per SQL 2005 o 2008
-
06-09-2019 - |
Domanda
Ho un file CSV e ho bisogno di importarlo a una tabella in SQL 2005 o 2008. I nomi delle colonne e contare nel csv sono diversi dai nomi delle colonne della tabella e contare. Il csv è diviso da un ';' .
Esempio
CSV FileContents:
FirstName;LastName;Country;Age
Roger;Mouthout;Belgium;55
SQL persona tabella
Columns: FName,LName,Country
Soluzione
Mi piacerebbe creare una tabella temporanea, alla rinfusa inserire il sacco, selezionare nella nuova tabella che cosa avete bisogno e eliminare la tabella temporanea.
Qualcosa di simile
CREATE TABLE dbo.TempImport
(
FirstName varchar(255),
LastName varchar(255),
Country varchar(255),
Age varchar(255)
)
GO
BULK INSERT dbo.TempImport FROM 'PathToMyTextFile' WITH (FIELDTERMINATOR = ';', ROWTERMINATOR = '\n')
GO
INSERT INTO dbo.ExistingTable
(
FName,
LName,
Country
)
SELECT FirstName,
LastName,
Country
FROM dbo.TempImport
GO
DROP TABLE dbo.TempImport
GO
Altri suggerimenti
È possibile utilizzare un file di formato durante l'importazione con BCP:
Crea un file di formato per la vostra tavola:
bcp [table_name] format nul -f [format_file_name.fmt] -c -T
9.0
4
1 SQLCHAR 0 100 "," 1 FName SQL_Latin1_General_CP1_CI_AS
2 SQLCHAR 0 100 "," 2 LName SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 100 "," 3 Country SQL_Latin1_General_CP1_CI_AS
4 SQLCHAR 0 100 "\r\n" 0 Age SQL_Latin1_General_CP1_CI_AS
Modificare il file di importazione. Il trucco è quello di aggiungere una riga fittizia per il campo che si desidera saltare, e aggiungere un '0' come ordine delle colonne del server.
quindi importare i dati utilizzando questo file di formato, specificando il file di input, questo file formato e il separatore:
bcp [table_name] in [data_file_name] -t , -f [format_file_name.fmt] -T
Io ora preferisco usare i file in formato XML come questo con BULK INSERT o OPENROWSET:
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="|" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
<FIELD ID="2" xsi:type="CharTerm" TERMINATOR="|" MAX_LENGTH="37"/>
<FIELD ID="3" xsi:type="CharTerm" TERMINATOR="|" MAX_LENGTH="41"/>
<FIELD ID="4" xsi:type="CharTerm" TERMINATOR="|" MAX_LENGTH="17"/>
<FIELD ID="5" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="10" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="i" xsi:type="SQLCHAR"/>
<COLUMN SOURCE="2" NAME="j" xsi:type="SQLUNIQUEID"/>
<COLUMN SOURCE="3" NAME="k" xsi:type="SQLNUMERIC" PRECISION="18" SCALE="0"/>
<COLUMN SOURCE="4" NAME="l" xsi:type="SQLBINARY"/>
<COLUMN SOURCE="5" NAME="m" xsi:type="SQLVARYCHAR"/>
</ROW>
</BCPFORMAT>
Quindi è possibile utilizzare il comando BULK INSERT lato server come segue:
BULK INSERT foo FROM '\\mydomain.com\bar\bletch' WITH (FORMATFILE='foo.xml', ERRORFILE='foo.errors', FIRSTROW = 1, BATCHSIZE=10000)
In alternativa, se si desidera modificare i dati 'in volo', è possibile utilizzare il
INSERT foo(i, j,k)
SELECT foo_delimited.i, foo_delimited.j, foo_delimited.k * 2
OPENROWSET(BULK 'foo',
FORMATFILE= 'foo.xml')
AS foo_delimited
Per info, con la stessa struttura, è possibile utilizzare questo tipo di dichiarazione:
bcp schema.Table in "/Samples/AdventureWorksDW/DimCurrency.csv" \
-S db.url \
-d databaseName \
-U userName \
-P pwd \
-t ; `# The field separator ` \
-c `# Insert as character and doesn't ask the data type` \
-q `# With quote -- seems to be mandatory`