2009-10-07 10 views
9

Ho un SQLClient.DataSet in VB.NET e voglio inserire l'intera cosa in una tabella di SQL Server senza dover fare quanto segue :È possibile inserire un'intera DataTable VB.NET in un server SQL in una volta

For Each dr as Datarow in MyDataset 
    Dim sc As New SqlCommand("INSERT INTO MyNewTable " & _ 
          "VALUES (@column1, @column2)", MyDBConnection) 
    sc.Parameters.AddWithValue("@column1", dr.Item(0)) 
    sc.Parameters.AddWithValue("@column2", dr.Item(1)) 
    sc.ExecuteNonQuery() 
Next 

Dal momento che ho avuto quasi un milione di righe (tutti piuttosto magro, quindi non è molto spazio), io ovviamente non voglio correre questo ciclo e generare un milione di istruzioni INSERT.

So che un'opzione è quella di utilizzare un server collegato quando prelevo i dati inizialmente, poiché proviene da un altro server SQL, e basta averlo nell'INSERTO da lì. Tuttavia, se ho già i dati nella mia domanda, c'è un modo più efficiente per inserirli in blocco? Posso in qualche modo passare DataTable come parametro a SQL Server e farlo separare e inserire le righe?

risposta

14

provare con SqlBulkCopy

+0

Questo sembra essere esattamente quello che volevo. Non avevo idea che questa classe esistesse - grazie! – SqlRyan

+0

Ha inserito tutti i record di un milione in circa quattro secondi: è perfetto. Grazie ancora! – SqlRyan

2

Si potrebbe chiamare .WriteXML() sul DataSet e dump che nel database in un inserto.

3

Utilizzare l'InsertCommand di SqlDataAdapter per definire la query di inserimento. Quindi chiama il metodo di aggiornamento di DataAdapter con il set di dati come parametro per fare in modo che spinga i dati.

Qualcosa di simile:

Dim DA As SqlDataAdapter = New SqlDataAdapter 
Dim Parm As New SqlParameter 

DA.InsertCommand = New SqlCommand("Insert Into tbl1(fld0, fld1, fld2) Values(@fld0, @fld1, @fld2)", conn) 
Parm = DA.InsertCommand.Parameters.Add(New SqlParameter ("@fld0", NVarChar, 50, "fld0")) 
Parm = sqlDA.InsertCommand.Parameters.Add(New SqlParameter ("@fld1", SqlDbType.NVarChar, 50, "fld1")) 
Parm = sqlDA.InsertCommand.Parameters.Add(New SqlParameter ("@fld2", SqlDbType.NVarChar, 50, "fld2")) 
DA.Update(dataset1, "tbl1") 
+0

Ho considerato questa idea, ma penso che generi ancora un'istruzione INSERT per ogni riga. Almeno lo fa in background, quindi, è sicuramente più pulito. – SqlRyan

+1

Mi rendo conto che questo è un vecchio post ma questo articolo MSDN sembra pertinente in termini di prestazioni ... Se le tabelle di origine e destinazione si trovano nella stessa istanza di SQL Server, è più facile e veloce utilizzare un'istruzione INSERT ... Transact-SQL SELECT copiare i dati. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.90).aspx – htm11h

6

Con SQL Server 2008 è possibile utilizzare Table-Valued Parameters:

Dim sc As New SqlCommand(
    "INSERT INTO MyNewTable (field1, field2,...)"& 
    "SELECT field1, field2,... FROM @MyTable;", MyDBConnection) 
sc.Parameters.AddWithValue("@MyTable", MyDataset) 
sc.ExecuteNonQuery() 
+0

Mi capita di usare il 2008, ed è un'idea fantastica! Mi chiedo come il rendimento si paragona a SQLBulkCopy - lo sto facendo su una LAN gigabit adesso, ma su una connessione WAN più lenta, qualche idea del confronto? – SqlRyan

+0

Le prestazioni saranno determinate dalla velocità di trasferimento (da client a server) e la differenza tra la quantità di dati tra copia bulk e TVP è minima, quindi dovrebbero comportarsi in modo simile. Misura migliore –

Problemi correlati