Domanda

Sto esportando i dati in modo programmatico da Excel a SQL Server 2005 usando SqlBulkCopy. Funziona benissimo, l'unico problema che ho è che non conserva la sequenza di righe che ho nel file Excel. Non ho una colonna da ordinare, voglio solo che i record vengano inseriti nello stesso ordine in cui compaiono nel foglio di calcolo di Excel.

Non riesco a modificare il file Excel e devo lavorare con quello che ho. L'ordinamento per una delle colonne esistenti interromperà la sequenza.

Per favore aiutate.

P.S. Finito con l'inserimento della colonna ID nel foglio di calcolo, sembra che non ci sia modo di mantenere l'ordine durante l'esportazione / importazione

È stato utile?

Soluzione

Non credo che l'ordinamento delle righe sia specificato o garantito da SQL a meno che tu non utilizzi un " ORDER BY " Clausola.

Da un post di Bill Vaughn ( http://betav.com/ blog / billva / 2008/08 / sql_server_indexing_tips_and_t.html ):

  

Utilizzo di Ordina per: Anche quando è presente una tabella   un indice cluster (che memorizza il file   dati in ordine fisico), SQL Server   non garantisce che le righe saranno   restituito in quel (o qualsiasi particolare)   ordine a meno che non sia una clausola ORDER BY   usato.

Un altro collegamento con informazioni:

http://sqlblogcasts.com/blogs/simons/archive/2007/08/21/What-is-the-position-of-a-row--.aspx

Altri suggerimenti

Dopo molte ricerche sembra evidente che non c'è modo di mantenere l'ordine delle righe con il comando Bulk Insert scritto come è descritto da Microsoft. Devi aggiungere tu stesso una colonna ID direttamente nel file di importazione, usare una shell o altri script esterni, o ne fai a meno. Sembra che sarebbe una funzionalità necessaria (e facile) per Microsoft da aggiungere, ma dopo più di un decennio di nulla da loro, non accadrà.

Tuttavia, dopo l'importazione, dovevo conservare l'ordine dei record effettivi nel file di importazione poiché i record con valori superiori sostituivano quelli inferiori se una colonna impostata avesse lo stesso valore.

Quindi ho seguito un percorso diverso. I miei vincoli erano:

  • Non ho potuto cambiare affatto il file sorgente. (e imposta un precedente negativo!)
  • Non ho potuto usare uno script esterno. Troppo complicato. Doveva essere una semplice soluzione basata su T-Sql, nessuna esecuzione CMD. Ciò doveva andare in un'unica procedura in modo da poter essere automatizzato.

Mi è piaciuta la logica dell'uso di Powershell per creare istruzioni di inserimento ordinate per ogni riga, quindi in esecuzione in SQL. Sostanzialmente stava mettendo in coda ogni record per l'inserimento individuale piuttosto che per l'inserimento BULK. Sì, funzionerebbe, ma sarebbe anche molto lento. Ho spesso file con oltre 500K righe. Avevo bisogno di qualcosa di VELOCE.

Quindi ho incontrato XML. Carica in blocco il file direttamente in una singola variabile XML. Ciò manterrebbe l'ordine dei record man mano che ciascuno viene aggiunto all'XML. Quindi analizza la variabile XML e inserisci i risultati in una tabella, aggiungendo una colonna identità allo stesso tempo.

Si presume che il file di importazione sia un file di testo standard, con ogni record che termina con un avanzamento riga (Char (13) + Char (10))

Il mio approccio prevede 2 passaggi:

  1. Esegue l'istruzione IMPORT SQL (usando OPENROWSET), incapsulando ogni record con tag XML. Cattura i risultati in una variabile XML.

  2. Analizza la variabile dai tag XML in una tabella, aggiungendo una colonna [ID] incrementale.

    ---------------------------------
    Declare @X xml;
    ---------------------------------
    SELECT @X=Cast('<X>'+Replace([BulkColumn],Char(13)+Char(10),'</X><X>')+'</X>' as XML)
    FROM OPENROWSET (BULK N'\\FileServer\ImportFolder\ImportFile_20170120.csv',SINGLE_CLOB) T
    ---------------------------------
    SELECT [Record].[X].query('.').value('.','varchar(max)') [Record]
    ,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) [ID]
    --Into #TEMP 
    FROM @X.nodes('X') [Record](X);
    ---------------------------------
    
    • I tag XML sostituiscono ogni avanzamento riga.

    • Se il file termina con un avanzamento riga, ciò causerà l'aggiunta di una riga vuota alla fine. Elimina semplicemente l'ultima riga.

Ho scritto questo nella mia procedura usando sql dinamico in modo da poter passare il FileName e impostare l'ID per iniziare da 1 o 0 (nel caso in cui ci sia una riga di intestazione).

Sono stato in grado di eseguirlo su un file di 300.000 record in circa 5 secondi.

Potresti anche essere in grado di definire una colonna identità nella tabella che si auto-incrementa durante il caricamento dei dati. In questo modo, puoi ordinarlo in un secondo momento quando desideri che i record tornino nello stesso ordine.

Se puoi salvare il foglio di calcolo Excel come CSV, è molto semplice generare un elenco di istruzioni INSERT con qualsiasi linguaggio di script che verrà eseguito nello stesso ordine del foglio di calcolo. Ecco un rapido esempio in Groovy ma qualsiasi linguaggio di scripting lo farà altrettanto facilmente se non più facilmente:

def file1 = new File('c:\\temp\\yourSpreadsheet.csv')
def file2 = new File('c:\\temp\\yourInsertScript.sql')

def reader = new FileReader(file1)
def writer = new FileWriter(file2)

reader.transformLine(writer) { line ->
    fields =  line.split(',')

    text = """INSERT INTO table1 (col1, col2, col3) VALUES ('${fields[0]}', '${fields[1]}', '${fields[2]}');"""

}

Puoi quindi eseguire il tuo " yourInsertScript.sql " rispetto al tuo database e il tuo ordine sarà lo stesso del tuo foglio di calcolo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top