2014-06-12 6 views
5

Sto cercando un modo per esportare una tabella SQL Server in un file CSV.Esportazione batch del database SQL in CSV con citazioni di escape

Esistono alcune soluzioni che utilizzano sqlcmd o bcp, ma finora non ne ho trovate nessuna che risparmi correttamente virgolette, virgole o interruzioni di riga.

Per esempio, questo comando consente di creare un bel csv, ma non ignora le citazioni e le virgole, che rende il file CSV inutilizzabile:

bcp MyDatabase..MyTable out c:\test.csv -c -T -t, -r\n -S MYPC 

Dai miei dati campione di quattro righe ciascuna contenente qualche altro carattere speciale questo sarebbe creare un file In questo modo:

1,contains " quote 
2,contains , comma 
3,contains ; semi 
4,contains ' single quote 

A causa delle virgolette e della virgola questo non è impostabile da altri programmi. Ovviamente potrei cambiare il separatore in tab o il simbolo pipe, ma questo non risolve il problema reale: qualunque sia il separatore, se esiste nei dati renderà il file di esportazione inutilizzabile.

Quindi, come faccio a esportare in serie i dati in un batch in un file csv funzionante utilizzando strumenti SQL standard come BCP, sqlcmd o simili?

+0

il pacchetto SSIS sarebbe un'opzione? – wmz

risposta

1

ho trovato una soluzione che codifica correttamente i file csv in another Stackoverflow answer di Iain Elder:

Egli usa PowerShell per esportare corretta csv:

Import-Module -Name SQLPS 
$cd = Get-Location 
Invoke-Sqlcmd -Query "SELECT * FROM DimDate;" ` 
       -Database AdventureWorksDW2012 ` 
       -Server localhost | 
Export-Csv -NoTypeInformation ` 
      -Path "$cd\DimDate.csv" ` 
      -Encoding UTF8 

La sua soluzione codifica correttamente delimitatori, linea interrompe, cita e funziona anche con contenuti lunghi.

Ancora mi sembra strano che nessun'altra esportazione sembra supportare correttamente csv. Non è quello complicato.

-1

Deve essere csv? Di solito preferisco i file txt per evitare questo tipo di problema.

 bcp MyDatabase..MyTable out c:\test.csv -c -T , -r\n -S MYPC 

Se avete la possibilità di usare altri delimitatori cercano

 bcp MyDatabase..MyTable out c:\test.csv -c -t| -T, -r\n -S MYPC 

Altri modi per raggiungere csv ben formati sono di misura descritto qui: https://www.simple-talk.com/sql/database-administration/creating-csv-files-using-bcp-and-stored-procedures/

+1

farebbe bene anche il txt, ma la soluzione ha lo stesso problema: cosa succede se il delimitatore (|), l'elemento Separazione (,) o la separazione delle righe (\ n) esiste negli elementi della tabella? BCP non sfuggirà a questi personaggi, quindi la tua soluzione avrà gli stessi problemi del mio, fallirà su caratteri diversi. – Sam

+0

Potresti scegliere un separatore archiviato che è molto improbabile che compaia nei tuoi dati. Abbiamo visto le soluzioni utilizzando # * # come delimitatore di campo – Narti

+1

l'estremità ricevente funziona solo con delimitatori single-char e "improbabile" di solito si interrompe il martedì successivo:/ – Sam

1

O renderlo larghezza fissa o aggiungere manualmente delimitatori di citazione . Entrambi questi possono essere raggiunti con una vista

Per esempio il vostro vista sarebbe

SELECT C1, '"' + REPLACE(C2,'"','\"') + '"' As C2 FROM YourTable 

Poi si seleziona da questo punto di vista nel vostro BCP e C2 saranno citazione delimitato, e le citazioni nei dati sarà scappato con \ (principalmente)

Per renderlo a larghezza fissa è solo un'altra espressione di stringa che concatena i campi con il riempimento appropriato.

È possibile utilizzare una query in BCP ma non sono sicuro di come si sfuggono le virgolette (!). Non importa quello che fai quelle citazioni sono un dolore.

+0

L'esportazione batch non può modificare il database per aggiungere viste. Proverò a usare la sostituzione in sqlcmd, però, grazie. – Sam

+0

Puoi usare una query, ma diventerà caotica. È inoltre possibile creare una vista in un database diverso che fa riferimento al database di origine se questo non deve essere portatile. Forse dovresti spiegare tutti i vincoli. –

+0

Se nessun separatore di campo è mai accettabile o affidabile, l'unica opzione è la larghezza fissa. –

4

Utilizzando quotename dovrebbe sfuggire correttamente citazioni (ma è limitato ad un massimo di 128 caratteri, senza interruzioni di linea):

BCP " select quotename(quotedCol,CHAR(34)),quotename(secondCol,CHAR(34))from 
testdb.dbo.table_1" queryout temp.csv -c -T -S. -t"," 

determinati valori this is "between quotes" e def che produce:
"this is ""between quotes""","def" che è credo correttamente citato/fuggito secondo le quidelines csv.

Fonte: http://social.technet.microsoft.com/wiki/contents/articles/4666.sql-server-bcp-utility-experts-guide.aspx#Use_Text_Qualifier_on_BCP_Output

+0

Sì, questo tipo di citazione è esattamente quello che sto cercando! Ma ovviamente il contenuto del mio campo contiene interruzioni di riga e sono più lunghi di 128 caratteri - non c'è qualcosa di simile anche per colonne più lunghe? – Sam

+0

Pensavo che SSIS potesse gestirlo correttamente, ma ovviamente l'ID no. È possibile ottenere l'output corretto, ma è necessaria una funzione personalizzata [column transform], così efficacemente è la stessa cosa proposta da @ElectricLlama. Se potessi definire una funzione personalizzata, forse funzionerebbe (non l'ho testata): http://nosqlsolution.blogspot.com/2012/07/problems-with-quotename.html – wmz

+0

Ho trovato una soluzione che utilizza PowerShell, che contiene uno scrittore CSV che può creare file CSV codificati correttamente, che funziona anche con grandi stringhe: http://stackoverflow.com/a/23976218/7021 – Sam