2011-09-19 1 views
9

J'utilise openrowset pour importer un fichier csv dans SQL Server. L'une des colonnes du fichier csv contient des nombres en notation scientifique (1.08E + 05) et la colonne du tableau en cours d'insertionConvertir la notation scientifique en flottant lors de l'utilisation de OpenRowSet pour importer un fichier .CSV

Par défaut, il importe la valeur 1 et ignore le .08E + 05.

J'ai essayé d'utiliser cast() et convert() pour convertir la valeur directement lors de l'exécution de la requête, ainsi que pour configurer le type de données dans la table sous forme de chaîne de caractères et l'importer comme tel. Toutes ces méthodes ont le même comportement où le .08E + 05 est ignoré.

Y at-il un moyen d'avoir la valeur importée comme 108000 au lieu de 1 sans le .08E + 05 sans avoir à changer le fichier csv lui-même?

Configuration du type de données en tant que varchar et la lecture dans le fichier csv semble avoir le même effet avec le code suivant:

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 

pas toutes les valeurs dans le fichier CSV ont la notation scientifique et la valeur sans elle, par exemple 81000 traverser sans problème.

Répondre

13

Pour BULK INSERT les méthodes que j'ai souvent trouvé plus simple d'abord déplacer les données dans une table de tous varchars, puis se débarrasser des choses étrangères comme délimiteurs cités et fixer la mise en forme. Je me souviens d'avoir passé un bon moment à se débarrasser de la notation scientifique, vous pouvez juste jouer avec la table varchar jusqu'à ce que vous ayez raison. Je me souviens avoir essayé toutes sortes de combinaisons précision/échelle jusqu'à ce que j'en trouve une compatible. Je pense que pour moi, il était FLOAT alors DECIMAL(24,12) ...

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

EDIT ajoutant ce que je l'ai fait pour essayer de repro et/ou démontrer d'une manière moins alambiquée.

J'ai créé un fichier CSV très simple:

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

Je courais le code suivant (pour une raison quelconque, je ne peux pas MSDASQL à courir sur ma machine pour sauver ma vie):

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; 

Résultats:

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

En fait, dans votre cas, maintenant que je suis en train de relire la question que vous pouvez probablement utiliser 'SELECT CONVERT (INT , CONVERT (FLOAT, '1.08E + 05 ')); - la dernière fois que j'ai travaillé sur la notation scientifique, j'avais affaire à des compteurs de performance de LogMan, et j'avais absolument besoin des décimales ... –

+0

Toutes les solutions ci-dessus fonctionnent si je fournis la valeur explicitement. Dans le fichier CSV, j'ai un nom de colonne pour la valeur et si je l'utilise, par exemple CONVERT (INT, CONVERT (FLOAT, COLUMN_NAME_IN_CSV)) je reçois toujours le comportement où il lit seulement le premier chiffre. Pensées? – amarcy

+0

Mes pensées sont encore à insérer en vrac dans une table de varchars en premier. Il peut se passer quelque chose d'autre lorsque votre requête insert ... select from openrowset essaie de faire correspondre les types de tables aux métadonnées de la requête. Si vous insérez d'abord dans varchar, cela ne vous dérangera pas ... –

4

Est-ce que ça va être un vrai travail?

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

d'abord, le fait que vous avez une notation scientifique signifie probablement Excel ou son certains autre programme qui a créé la valeur a PERDU certaines données .... en d'autres termes, le nombre original à l'intérieur de la notation a été converti et ainsi certains nombres et précision ont été perdus. C'est un problème avec de nombreux produits Microsoft qui convertissent à partir d'Excel et CSV.

En second lieu, voici une meilleure piefce conversion qui convertit le nombre en chaîne:

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

..... a PERDU quelques données ...... c'est un problème avec de nombreux produits Microsoft qui convertissent à partir d'Excel et CSV ..... exactement. Un de plus. Ne pas avoir installé Excel est à peu près une condition préalable à tout type de travail de données. Le problème est que vos clients à désinstaller Excel est assez difficile :) – DaveBoltman

Questions connexes