2009-10-07 12 views
9

Mam obiekt SQLClient.DataSet w VB.NET i chcę wstawić całą rzecz do tabeli programu SQL Server bez konieczności wykonywania następujących czynności :Czy jest możliwe wstawienie całej tabeli danych VB.NET do SQL Server na raz?

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 

Ponieważ mam blisko milion wierszy (wszystkich bardzo chudy, więc to nie jest dużo miejsca), ja oczywiście nie chce uruchomić tę pętlę i wygenerować mln INSERT.

Wiem, że jedną z opcji jest użycie połączonego serwera podczas początkowego pobierania danych, ponieważ pochodzi on z innego serwera SQL i po prostu jest dostępny w INSERT. Jeśli jednak mam już dane w mojej aplikacji, czy istnieje skuteczniejszy sposób na wstawienie go luzem? Czy mogę jakoś przekazać DataTable jako parametr do SQL Server i mieć go posortować i wstawić wiersze?

Odpowiedz

14

spróbuj SqlBulkCopy

+0

To wydaje się być dokładnie to, co chciałem. Nie miałem pojęcia, że ​​ta klasa istnieje - dzięki! – SqlRyan

+0

Wstawił wszystkie miliony rekordów w około cztery sekundy - to jest idealne. Dzięki jeszcze raz! – SqlRyan

2

Można zadzwonić .WriteXML() na DataSet i zrzucić że do bazy danych w jednej wkładki.

3

Użyj InsertCommand SqlDataAdapter, aby zdefiniować zapytanie Insert. Następnie wywołaj metodę aktualizacji DataAdaptera z zestawem danych jako parametrem, który sprawi, że dane będą przepychane.

Coś jak:

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

Rozważałem ten pomysł, ale myślę, że nadal generuje instrukcję INSERT dla każdego wiersza. Przynajmniej robi to w tle, więc na pewno jest czystszy. – SqlRyan

+1

Zdaję sobie sprawę, że jest to stary post, ale ten artykuł MSDN wydaje się istotne w odniesieniu do wydajności ... Jeśli tabele źródłowe i docelowe są w tej samej instancji serwera SQL, jest łatwiej i szybciej używać instrukcji Transact-SQL INSERT ... SELECT skopiować dane. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.90).aspx – htm11h

6

SQL Server 2008 można użyć 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

Tak się składa, że ​​używam 2008 roku i to jest niesamowity pomysł! Zastanawiam się, jak wydajność porównuje się do SQLBulkCopy - robię to teraz przez gigabitową sieć LAN, ale przez wolniejsze połączenie WAN, jakikolwiek pomysł porównania? – SqlRyan

+0

Wydajność będzie zależeć od szybkości transferu (klient do serwera), a różnica w ilości danych między masową kopią i TVP jest minimalna, więc powinny zachowywać się podobnie. Lepszy środek. –

Powiązane problemy