Ecriture du résultat de sélection dans un fichier csv

37

Nous devons écrire les résultats de la requête SELECT dans un fichier csv. Comment faire pour utiliser T-SQL dans SQL Server 2008 R2? Je sais que cela peut être fait dans SSIS, mais pour certaines raisons, nous n'avons pas cette option.

J'ai essayé d'utiliser le proc suggéré dans l'article ci-dessous, mais lorsque j'exécute le proc, SQL se plaint de ne pouvoir exécuter sys.sp_OACreate et sys.sp_OADestroy qui sont appelés dans ce proc.

Savez-vous comment nous pouvons activer ces composants ou connaître un meilleur moyen d'écrire dans un fichier à l'aide de T-SQL?

Merci d'avance.

Ciel
la source

Réponses:

52

Utiliser l' utilitaire BCP

bcp "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable" queryout "D:\MyTable.csv" -c -t , -S SERVERNAME -T

L' -cargument spécifie c sortie haracter, par opposition au format binaire natif de SQL; la valeur par défaut à des valeurs séparées par une tabulation, mais -t ,modifie le champ t erminator à des virgules. -Tspécifie l'authentification Windows (" t rusted connection"), sinon use -U MyUserName -P MyPassword.

Cela n'exporte pas les en-têtes de colonne par défaut. Vous devez utiliser UNION ALL pour les en-têtes.

OU

Utilisez SQLCMD

SQLCMD -S SERVERNAME -E -Q "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable"
-s "," -o "D:\MyData.csv" 

OU

Utilisez Powershell

Voici un lien vers un article . Si vous finissez par utiliser cela, vous voudrez peut-être ajouter -notypeaprès Export-Csv $extractFilepour supprimer la colonne inutile du fichier de sortie.

RK Kuppala
la source
4
+1 Pour l'utilitaire BCP - il est très facile à utiliser, c'est l'outil le plus rapide que j'ai jamais utilisé pour exporter / importer des informations et il existe de nombreuses options. Je vous conseillerai d'ajouter "> NomFichier.log" à la fin de l'instruction - cela créera un fichier journal.
Gotqn
24

En ajoutant à la réponse précédente, ce qui vous aide à automatiser l’action. Si vous n’en avez besoin que de temps en temps, vous pouvez le faire dans Management Studio. Il vous suffit de cliquer avec le bouton droit de la souris sur l’en-tête - Enregistrer les résultats sous -> choisissez un fichier .csv .

Ou si vous souhaitez le faire pour chaque instruction select que vous exécutez, vous pouvez modifier le sens de sortie des résultats dans un fichier. Utilisez Outils -> Options -> Résultats de la requête - Résultats à archiver .

Un autre moyen, qui peut être automatisé facilement et utilise SSIS, consiste à utiliser la fonctionnalité Exporter les données de Management Studio. Faites un clic droit sur la base de données -> Tâches -> Exporter des données. Il y a un assistant avec beaucoup d'options. Vous devez choisir la base de données source, la destination et d'autres options. Pour la destination, assurez-vous qu'il s'agit d'un "fichier plat", parcourez-le et choisissez le type .csv. Choisissez le formatage souhaité. Vous obtiendrez à la fin un package SSIS pouvant être enregistré localement et répété si nécessaire.

Marian
la source
10

Utilisez T-SQL

INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0','Text;Database=D:\;HDR=YES;FMT=Delimited','SELECT * FROM [FileName.csv]')
SELECT Field1, Field2, Field3 FROM DatabaseName

Mais il y a quelques mises en garde:

  1. Vous devez disposer du fournisseur Microsoft.ACE.OLEDB.12.0. Le fournisseur Jet 4.0 fonctionnera aussi, mais il est ancien, alors j’ai utilisé celui-ci à la place.
  2. Le fichier .CSV devra déjà exister. Si vous utilisez des en-têtes (HDR = YES), assurez-vous que la première ligne du fichier .CSV est une liste délimitée de tous les champs.
Slogmeister Extraordinaire
la source
1
Meilleure réponse jusqu'à présent!
ajeh
1
excellent travail, y compris les mises en garde
JJS
5

Low tech, mais ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
la source
MySQL considère col1 + ',' + cast(col2 as varchar(10)) + ',' + col3comme un nom de colonne et affiche NULL partout.
Nikhil Wagh
4

Il semble que vous ayez déjà une solution acceptable, mais si vous avez configuré db mail, vous pouvez potentiellement faire quelque chose comme ceci:

EXEC msdb.dbo.sp_send_dbmail
    @recipients='[email protected]',
    @subject='CSV Extract', 
    @body='See attachment',
    @query ='SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'CSV_Extract.txt',
    @query_result_separator = ',',
    @query_result_header = 1

Si vous envoyez le fichier par courrier électronique quelque part, cela pourrait vous éviter quelques étapes.

Shane Estelle
la source
Juste ce que je cherchais, bravo à vous!
Mashchax
Bien que vous deviez ajouter le paramètre @nom_profil si vous n'avez pas de profil privé par défaut pour votre utilisateur ni de profil public pour la base de données.
Mashchax
1

Cela peut facilement être fait en 3 étapes:

  1. Ecrivez votre requête en tant que SELECT INTOrequête. Cela exportera essentiellement les résultats de votre requête dans une table.

    Select
      Field1
     ,Field2
     ,Field3
    INTO dbo.LogTableName         --Table where the query Results get logged into.
    From Table
    

    Notez que cette table ne peut pas exister lorsque la requête est exécutée, car ce type de requête souhaite créer la table dans le cadre de l'exécution.

  2. Ensuite, utilisez SSIS pour exporter les résultats de cette table .csv. L'assistant d'exportation SSIS vous permet de choisir votre délimiteur, etc. C'est très pratique pour utiliser un | délimiteur dans les cas où le jeu de résultats contient des virgules.

    Clic droit sur DB Name > Tasks > Export Data

  3. Une fois l'exportation terminée, exécutez la DROP TABLEcommande pour nettoyer votre table de journal.

    Drop Table dbo.LogTableName
Don Moehling
la source
3
Salut Don. J'ai ajouté du formatage à votre réponse. Vous pouvez cliquer sur "modifier" en bas à gauche pour voir ce qui a été modifié et cliquer sur le bit "édité" de "xx minutes" pour afficher l'historique complet si vous souhaitez revenir en arrière. ce qui a déjà été écrit et ne devrait pas attirer beaucoup d'attention.
Michael Green
0

J'utilise MS Access DoCMD pour exporter des fichiers CSV à partir de SQL Server. Il est capable de le faire avec une seule commande. La base de données access est uniquement utilisée pour activer la commande access. Il fonctionne bien et, comme avantage supplémentaire (vous ne savez pas pourquoi), il crée un fichier schema.ini pour la table exportée.

Adam

CMD="SELECT * INTO [Text;HDR=Yes;DATABASE=C:\].[Results.txt]  
FROM [ODBC;DSN=SQL2017;Description=SQL2017;UID=.;Trusted_Connection=Yes;APP=Microsoft Office 2013;WSID=LAPTOP-XYZ;DATABASE=TempDB_DataDump_1].Results "

 Set appAccess = CreateObject("Access.Application") 
                appAccess.OpenCurrentDatabase "anyAccessdatabase.mdb" 
                   ' appAccess.DoCmd.SetWarnings 0
                    appAccess.DoCmd.runsql "CMD"
Adam
la source
-1

Cette procédure générera un fichier CSV avec le résultat de la requête que vous transmettez en tant que paramètre. Le second paramètre est votre nom de fichier CSV, assurez-vous de le transmettre avec un chemin d'accès inscriptible valide.

Voici le script pour créer la procédure:

CREATE procedure [dbo].[usp_create_csv_file_from_query]
    @sql Nvarchar(MAX),
    @csvfile Nvarchar(200)
    as
    BEGIN
        if IsNull(@sql,'') = '' or IsNull(@csvfile,'') = ''
        begin
            RAISERROR ('Invalid SQL/CsvFile values passed!; Aborting...', 0, 1) WITH NOWAIT
            return
        end
        DROP TABLE if exists global_temp_CSVtable;
        declare 
            @columnList varchar(4000), 
            @columnList1 varchar(4000),
            @sqlcmd varchar(4000),
            @dos_cmd nvarchar(4000)

        set @sqlcmd = replace(@sql, 'from', 'into global_temp_CSVtable from')
        EXECUTE (@sqlcmd); 

        declare @cols table (i int identity, colname varchar(100))
        insert into @cols
        select column_name
        from information_schema.COLUMNS
        where TABLE_NAME = 'global_temp_CSVtable'

        declare @i int, @maxi int
        select @i = 1, @maxi = MAX(i) from @cols

        while(@i <= @maxi)
        begin
            select @sql = 'alter table global_temp_CSVtable alter column [' + colname + '] VARCHAR(max) NULL'
            from @cols
            where i = @i
            exec sp_executesql @sql
            select @i = @i + 1
        end

        SELECT 
             @columnList = COALESCE(@columnList + ''', ''', '') + column_name 
            ,@columnList1 = COALESCE(@columnList1 + ', ', '') + column_name
        from information_schema.columns
        where table_name =  'global_temp_CSVtable'
        ORDER BY ORDINAL_POSITION;

        SELECT @columnList = '''' + @columnList + '''';

        SELECT @dos_cmd='BCP "SELECT ' + @columnList + 
                        ' UNION ALL ' +
                        'SELECT * from ' + db_name() + '..global_temp_CSVtable" ' + 
                        'QUERYOUT ' + @csvfile + 
                        ' -c -t, -T'
        exec master.dbo.xp_cmdshell @dos_cmd, No_output 
        DROP TABLE if exists global_temp_CSVtable;
    end
Sharief Pareed
la source
2
les réponses en code seulement ne sont pas considérées comme acceptables ici - pourriez-vous ajouter quelques commentaires sur votre réponse et pourquoi cela fonctionne? (les commentaires de code aideraient probablement ici aussi)
George.Palacios
Oui, et pourriez-vous également ajouter un exemple indiquant comment vous l'utilisez avec succès?
Marcello Miorelli