2009-05-04 11 views
5

Używam edycji ekspresowej sql 2008 i próbuję wykonać wiele wierszy wstawić za pośrednictwem mojej aplikacji C#.Wstawianie wielu wierszy -> instrukcja przekracza maksymalną dozwoloną liczbę wartości 1000 wierszy

Mam około 100000 rekordów, które należy wstawić.

Dobrze wszystko pójdzie dobrze dla pierwszych 1000 rekordów potem dostaję błąd: „Liczbę wyrażenia wartości wiersza w INSERT przekracza maksymalną dozwoloną liczbę wartości 1000 wierszy”

Spojrzałem na mój typ danych kolumny -> int, więc to nie powinno być problemem. Sprawdziłem kod i wstawiam w krokach 500 rekordów.

Więc googotowałem, ale nie mogłem znaleźć nic użytecznego. Czy ktoś może wyjaśnić, dlaczego dostaję ten błąd i jeśli to możliwe, jak go rozwiązać.

+1

Czy możesz pokazać nam swój kod? Ten komunikat o błędzie powinien wystąpić tylko wtedy, gdy używasz wartości wiersza, np. INSERT INTO ... VALUES (...), (...), (...) <- 3 wiersze tutaj, a limit to 1000. –

+0

Czy potrzebujesz opóźnienia między zapytaniami o wstawianie? – nlucaroni

+0

Czy próbujesz wstawić jeden wiersz na raz? spróbuj wywołać procedurę przechowywaną, aby wykonać wszystkie wstawienia naraz (jeśli jeszcze tego nie robisz) – northpole

Odpowiedz

5

Można użyć klasy SQLBulkCopy. Który obsługuje grupowanie, transakcje i jest bardziej wydajny niż standardowe instrukcje wstawiania.

+0

"Jeśli tabele źródłowa i docelowa znajdują się w tej samej instancji serwera SQL, łatwiejsze i szybsze będzie korzystanie z języka Transact-SQL INSERT ... instrukcja SELECT do kopiowania danych. " Źródło: http://msdn.microsoft.com/en-us/library/s4s223c6.aspx Tylko dla płyty. :) – ShdNx

0

to jak mój kod obsługuje multi wkładkę

var count = "SELECT COUNT(*) as rowcount FROM table_mysql GROUP BY id"; 

var countReader = Retrieve(count); 
var countRows = 0; 
try 
{ 
    while (countReader.Read()) 
    { 
     countRows += int.Parse(countReader.GetValue(0).ToString()); 
    } 
} 
catch (Exception ex) 
{ 
    Log.LogMessageToFile("Import.cs -> table_mssql: " + ex.StackTrace + " /n" + ex.Message); 
} 
finally 
{ 
    if (countReader != null) { countReader.Close(); _crud.close_conn(); } 
} 

for (var a = 0; a < countRows;) 
{ 
    var sql = "SELECT id, traffic_id, dow, uu, imps, impsuu, otsw, otsm FROM table_mysql LIMIT " + a + ", " + (a + 500) + ""; 

    var reader = Retrieve(sql); 
    try 
    { 
     var builder = new StringBuilder(); 
     builder.Append(
      "SET IDENTITY_INSERT table_mssql ON;INSERT INTO table_mssql(id, traffic_id, dow, uu, imps, impsuu, otsw, otsm) VALUES "); 
     while (reader.Read()) 
     { 
      Application.DoEvents(); 
      try 
      { 
       builder.Append("(" + reader.GetValue(0) + ", " + reader.GetValue(1) + ", " + 
           reader.GetValue(2) + 
           ", " + reader.GetValue(3) + ", " + reader.GetValue(4) + 
           ", " + reader.GetValue(5) + ", " + reader.GetValue(6) + ", " + 
           reader.GetValue(7) + 
           "), "); 

      } 
      catch (Exception ex) 
      { 
       Log.LogMessageToFile("Import.cs -> table_mssql: " + ex.StackTrace + " /n" + ex.Message); 
      } 
     } 

     var sqlDB = builder.ToString(0, builder.Length - 2); 

     sqlDB += ";SET IDENTITY_INSERT table_mssql OFF;"; 
     if (!InsertDB(sqlDB)) 
     { 
      Log.LogMessageToFile("Import.cs -> table_mssql: No insert happend!"); 
     } 
    } 
    catch (Exception ex) 
    { 
     Log.LogMessageToFile("Import.cs -> table_mssql: " + ex.StackTrace + " /n" + ex.Message); 
     return false; 
    } 
    finally 
    { 
     if (reader != null) 
     { 
      reader.Close(); 
      _crud.close_conn(); 
     } 
    } 
    a = a + 500; 
} 

Idę sprawdzić sqlbulkcopy. Może to lepsze rozwiązanie.

+0

Jak wskazano powyżej lassevk, limit tej metody wynosi 1000 wierszy. Możesz zajrzeć do składni INSERT INTO tblName SELECT ... FROM otherTbl, ponieważ to, co robisz, wydaje się pochodzić niemal bezpośrednio z innej instrukcji SQL. Nie ma limitu wierszy na ten temat. – Eric

0

Można przyjąć, że całość w dół do tego:

var sql = "SET IDENTITY_INSERT table_mssql ON;" 
     + "INSERT INTO table_mssql" 
     +  "(id, traffic_id, dow, uu, imps, impsuu, otsw, otsm)" 
     + " SELECT id, traffic_id, dow, uu, imps, impsuu, otsw, otsm " 
     + " FROM table_mysql;" 
     + "SET IDENTITY_INSERT table_mssql OFF;"; 

if (!InsertDB(sqlDB)) 
{ 
    Log.LogMessageToFile("Import.cs -> table_mssql: No insert happend!"); 
} 

również: trzeba wiedzieć, że SQL Server nie obsługuje MySQL LIMIT słowa kluczowego. Zamiast tego używa on TOP lub ROW_NUMBER.

+0

Czy ma to również zastosowanie, gdy pierwsze zapytanie uzyskuje dostęp do bazy danych mysql w celu pobrania danych? Potrzebuję przenieść dane z bazy danych mysql do mojego lokalnego serwera sql 2008 express. – Gerbrand

+0

Ah, teraz otrzymuję konwencję nazywania. Twój fragment kodu i tekst pytania sprawiają, że wygląda na to, że wszystko przechodzi przez to samo połączenie, nazwy lub brak imion. W takim przypadku będziesz musiał krótko przechowywać dane na swoim kliencie, a BULK_INSERT jest zdecydowanie najszybszą opcją. –

+0

Lub, przy odrobinie szczęścia, może być możliwe podłączenie mysql db do serwera sql jako źródło danych db db: http://developer.infi.nl/index.php?ID=6&article=6 –

Powiązane problemy