2011-09-19 12 views
9

Sto utilizzando openrowset per importare un file csv in SQL Server. Una delle colonne nel file csv contiene numeri in notazione scientifica (1.08E + 05) e la colonna nella tabella in cui viene inseritaConverte notazione scientifica in virgola mobile quando si utilizza OpenRowSet per importare un file .CSV

Per impostazione predefinita, importa il valore 1 e ignora il valore .08E + 05.

Ho provato a utilizzare cast() e convert() per convertire il valore direttamente quando viene eseguita la query, nonché impostare il tipo di dati nella tabella come stringa di caratteri e importarlo come tale. Tutti questi metodi hanno lo stesso comportamento in cui il .08E + 05 viene ignorato.

C'è un modo per avere il valore importato come 108000 anziché 1 senza .08E + 05 senza dover modificare il file csv stesso?

Impostazione del tipo di dati come un varchar e la lettura nel file CSV sembra avere lo stesso effetto con il seguente codice:

CREATE TABLE #dataTemp (StartDate datetime, Value varchar(12)) 

SET @insertDataQuery = 'SELECT Date, CSVValue from OpenRowset(''MSDASQL'', ''Driver={Microsoft Text Driver (*.txt; *.csv)}; DefaultDir=' 
SET @insertDataQuery = @insertDataQuery + 'C:\Data\;'',''SELECT * FROM '+ '11091800.csv' + ''')' 

INSERT INTO #dataTemp EXEC(@insertDataQuery) 

SELECT * FROM #dataTemp 

Non tutti i valori nel file CSV avere la notazione scientifica e la valore senza di esso, ad es 81000 si imbattono senza problemi.

risposta

13

Per BULK INSERT metodologie ho spesso trovato più semplice per spostare prima i dati in una tabella di tutti i VARCHAR, poi sbarazzarsi di cose estranee come delimitatori quotate e fissare la formattazione. Ricordo di aver avuto un bel pò di tempo per liberarmi della notazione scientifica, puoi solo giocare con il tavolo varchar fino a quando non lo fai nel modo giusto. Ricordo di aver provato tutti i tipi di combinazioni di precisione/scala finché non ne ho trovato uno compatibile. Penso che per me è stato FLOAT poi DECIMAL(24,12) ...

SELECT CONVERT(DECIMAL(24, 12), CONVERT(FLOAT, '1.08E+05'));

EDIT aggiungendo quello che ho fatto per cercare di repro e/o dare prova di un modo meno contorto.

ho creato un semplice file CSV:

StartDate,Value 
20110808,81000 
20110808,1.08E+05 

Poi ho eseguito il seguente codice (per qualche motivo non riesco a MSDASQL per funzionare sulla mia macchina per salvare la mia vita):

CREATE TABLE #dataTemp(StartDate DATETIME, Value VARCHAR(32)); 

BULK INSERT #dataTemp FROM 'C:\data\whatever.csv' 
    WITH (ROWTERMINATOR='\n', FIELDTERMINATOR=',', FIRSTROW = 2); 

SELECT * FROM #dataTemp 
GO 
SELECT StartDate, CONVERT(INT, CONVERT(FLOAT, Value)) FROM #dataTemp; 
GO 
DROP TABLE #dataTemp; 

Risultati:

StartDate    Value 
----------------------- -------- 
2011-08-08 00:00:00.000 81000 
2011-08-08 00:00:00.000 1.08E+05 

StartDate    (No column name) 
----------------------- ---------------- 
2011-08-08 00:00:00.000 81000 
2011-08-08 00:00:00.000 108000 
+1

In realtà nel tuo caso ora che sto rileggendo la questione probabilmente si può semplicemente usare 'selezionare Converti (INT , CONVERT (FLOAT, '1.08E + 05 ')); '- l'ultima volta che ho lavorato sulla notazione scientifica avevo a che fare con i contatori delle prestazioni di LogMan, e avevo sicuramente bisogno delle cifre decimali ... –

+0

Qualsiasi delle soluzioni di cui sopra funziona se fornisco il valore esplicitamente. Nel file CSV ho il nome di una colonna per il valore e se lo uso, ad esempio CONVERT (INT, CONVERT (FLOAT, COLUMN_NAME_IN_CSV)) ho ancora il comportamento in cui legge solo la prima cifra. Pensieri? – amarcy

+0

I miei pensieri devono ancora essere inseriti in una tabella di varchar per primi. Potrebbe esserci qualcos'altro in corso quando l'inserto ... selezionare dalla query openrowset sta cercando di abbinare i tipi di tabella ai metadati dalla query. Se stai inserendo in varchar per primo, non gli interesserà ... –

4

Lo getterò come un vero lavoro?

select cast('1.08E+05' as real) 
5

Prima di tutto, il fatto che si hanno una notazione scientifica significa che la sua probabile Excel o qualche un altro programma che ha creato il valore ha perso alcuni dati .... in altre parole, il numero originale all'interno della notazione è stato convertito e quindi sono stati persi alcuni numeri e la precisione. questo è un problema con molti prodotti Microsoft che convertono da Excel e CSV.

In secondo luogo, qui è una migliore piefce conversione che converte il numero in una stringa:

CONVERT(nvarchar(255),LTRIM(RTRIM(str(ISNULL(YOUR_NUMBER,0),20,0)))) 
+1

..... ha perso alcuni dati ...... questo è un problema con molti prodotti Microsoft che convertono da Excel e CSV ..... esattamente. Più uno. Non aver installato Excel è praticamente un prerequisito per qualsiasi tipo di lavoro di dati. Il problema è far sì che i tuoi clienti disinstallino Excel è abbastanza difficile :) – DaveBoltman