2012-10-25 5 views
2

SQL Server에 sqlite 테이블을 복사하기 위해 데이터 테이블을 읽지 않고 C#으로 전환 할 수 있습니까?sqlite에서 SQL Server로 데이터 복사

sqlite 데이터베이스가 메모리에 있으며 수백만 개의 행을 포함하므로 절대적으로 필요한 경우가 아니라면 데이터 테이블에 복사하지 않으려합니다.

감사 KevCri

+0

[SqliteDataReader] (http://sqlite.phxsoftware.com/)를 사용하여 행을 반복 할 수 있습니다. – swasheck

답변

1

질문이 오래된 경우에도 나중에 참조 할 수 있도록 일부 소스 코드에 답하고 싶습니다. 나는 똑같은 문제점을 가지고 있었고이 게시물을 발견했다. 트릭을 수행 할 콘솔 애플리케이션을 만들었습니다. 뷰가 아닌 테이블에서만 작동하며 제한된 데이터 집합에서만 테스트했습니다. 그러나 이론적으로 SQLite 데이터베이스를 Microsoft SQL Server로 변환/복사하고 메모리를 거의 사용하지 않아야합니다.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SQLite; 
using System.Data.SqlClient; 
using System.Data; 

namespace SQLite2MSSQL 
{ 
    class Program 
    { 
    private static SQLiteConnection m_sqlitecon; 
    private static SqlConnection m_sqlcon; 

    private static List<KeyValuePair<string, string>> getSQLiteSchema(string tablename) 
    { 
     using (var cmd = new SQLiteCommand("PRAGMA table_info(" + tablename + ");", m_sqlitecon)) 
     { 
      var table = new DataTable(); 

      SQLiteDataAdapter adp = null; 
      try 
      { 
      adp = new SQLiteDataAdapter(cmd); 
      adp.Fill(table); 
      List<KeyValuePair<string, string>> res = new List<KeyValuePair<string, string>>(); 
      for (int i = 0; i < table.Rows.Count; i++) 
      { 
       string key = table.Rows[i]["name"].ToString(); 
       string value = table.Rows[i]["type"].ToString(); 
       KeyValuePair<string, string> kvp = new KeyValuePair<string, string>(key, value); 

       res.Add(kvp); 
      } 
      return res; 
      } 
      catch (Exception ex) { Console.WriteLine(ex.Message); } 
     } 
     return null; 
    } 

    private static void transfer(string tablename, List<KeyValuePair<string, string>> schema) 
    { 
     using (SQLiteCommand cmd = new SQLiteCommand("select * from " + tablename, m_sqlitecon)) 
     { 
     using (SQLiteDataReader reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
      StringBuilder sql = new StringBuilder(); 
      sql.Append("insert into " + tablename + " ("); 
      bool first = true; 
      foreach (KeyValuePair<string, string> column in schema) 
      { 
       if (first) 
       first=false; 
       else 
       sql.Append(","); 
       sql.Append("["+column.Key+"]"); 
      } 
      sql.Append(") Values("); 
      first = true; 
      foreach (KeyValuePair<string, string> column in schema) 
      { 
       if (first) 
       first = false; 
       else 
       sql.Append(","); 
       sql.Append("@"); 
       sql.Append(column.Key); 
      } 
      sql.Append(");"); 
      try 
      { 
       using (SqlCommand sqlcmd = new SqlCommand(sql.ToString(), m_sqlcon)) 
       { 
       foreach (KeyValuePair<string, string> column in schema) 
       { 
        sqlcmd.Parameters.AddWithValue("@" + column.Key, reader[column.Key]); 
       } 
       int count = sqlcmd.ExecuteNonQuery(); 
       if (count == 0) 
        throw new Exception("Unable to insert row!"); 
       } 
      } 
      catch (Exception Exception) { 
       string message = Exception.Message; 
       int idx = message.IndexOf("Violation of PRIMARY KEY"); 
       if (idx < 0) 
       throw; 
      } 
      } 
     } 
     } 
    } 

    private static bool SQLTableExists(string tablename) 
    { 
     using (SqlCommand cmd = new SqlCommand("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '" + tablename + "'", m_sqlcon)) 
     { 
     using (SqlDataReader reader = cmd.ExecuteReader()) 
     { 
      if (reader.HasRows) 
      return true; 
     } 
     } 
     return false; 
    } 


    private static string ReplaceCaseInsensitive(string str, string oldValue, string newValue) 
    { 
     int prevPos = 0; 
     string retval = str; 
     // find the first occurence of oldValue 
     int pos = retval.IndexOf(oldValue, StringComparison.InvariantCultureIgnoreCase); 

     while (pos > -1) 
     { 
     // remove oldValue from the string 
     retval = retval.Remove(pos, oldValue.Length); 

     // insert newValue in its place 
     retval = retval.Insert(pos, newValue); 

     // check if oldValue is found further down 
     prevPos = pos + newValue.Length; 
     pos = retval.IndexOf(oldValue, prevPos, StringComparison.InvariantCultureIgnoreCase); 
     } 

     return retval; 
    } 

    static void Main(string[] args) 
    { 
     // Connect to SQLite and SQL Server database 
     m_sqlitecon = new SQLiteConnection("Data Source=C:\\sqlitedatabases\\mydb.sqlite;Version=3;"); 
     m_sqlitecon.Open(); 
     m_sqlcon = new SqlConnection("Data Source=localhost;Initial Catalog=mydb;User Id="+userid+";password="+password+";MultipleActiveResultSets=True"); 
     m_sqlcon.Open(); 
     string sql = "SELECT * FROM sqlite_master WHERE type='table'"; 
     SQLiteCommand command = new SQLiteCommand(sql, m_sqlitecon); 
     SQLiteDataReader reader = command.ExecuteReader(); 
     List<string> tables = new List<string>(); 
     // Loop through all tables 
     while (reader.Read()) 
     { 
     string tablename = reader["name"].ToString(); 
     string sqlstr = reader["sql"].ToString(); 
     // Only create and import table if it does not exist 
     if (!SQLTableExists(tablename)) 
     { 
      Console.WriteLine("Creating table: " + tablename); 
      // Vi retter SQLite SQL til M$ SQL Server 
      sqlstr = ReplaceCaseInsensitive(sqlstr,"] BOOLEAN", "] bit"); 
      sqlstr = ReplaceCaseInsensitive(sqlstr,"] BLOB", "] varbinary(max)"); // Note, maks 2 GB i varbinary(max) kolonner 
      sqlstr = ReplaceCaseInsensitive(sqlstr,"] VARCHAR", "] nvarchar"); 
      sqlstr = ReplaceCaseInsensitive(sqlstr, "] nvarchar,", "] nvarchar(max),"); 
      sqlstr = ReplaceCaseInsensitive(sqlstr, "] nvarchar\r", "] nvarchar(max)\r"); // Case windiows 
      sqlstr = ReplaceCaseInsensitive(sqlstr, "] nvarchar\n", "] nvarchar(max)\n"); // Case linux 
      sqlstr = ReplaceCaseInsensitive(sqlstr, "] INTEGER", "] int"); 
      sqlstr = ReplaceCaseInsensitive(sqlstr, "] TEXT", "] nvarchar(max)"); 
      SqlCommand sqlcmd = new SqlCommand(sqlstr, m_sqlcon); 
      sqlcmd.ExecuteNonQuery(); 
      sqlcmd.Dispose(); 
      List<KeyValuePair<string, string>> columns = getSQLiteSchema(tablename); 
      // Copy all rows to MS SQL Server 
      transfer(tablename, columns); 
     } 
     else 
      Console.WriteLine("Table already exists: " + tablename); 
     } 
    } 
    } 
} 
+1

위대한 유틸리티 코드를 이용해 주셔서 감사합니다. 나는 단지 작은 문제 하나를 발견했다. 리버스 엔지니어링과 임포트를 위해 선택한 테이블이 필드 이름을 구분하는 '['대괄호를 가지지 않았기 때문에 여러분이 사용한 replace 문은 파울이되었습니다 ... 작은 변화 ...하지만 여전히 가치있는 코드 조각입니다. –

+0

대괄호는 공백이 포함 된 열에서 주로 사용됩니다. 나는 SQLite 드라이버의 버전이 다른 테이블 스키마 (괄호의 유무와 상관없이)에서 출력 될 수 있다고 생각한다. – nivs1978

0

ODBC driver SQLite는 존재합니다. SSIS 설치에 액세스 할 수 있으면 데이터 가져 오기 작업을 사용하여 테이블을 가져올 수 있습니다. 더 쉬운 방법은 SQL Server 가져 오기/내보내기 마법사를 사용하는 것입니다.

또 다른 옵션은 SQLite 데이터베이스에 대한 ODBC DSN을 만든 다음 OPENROWSET을 사용하여 SQLite에서 SQL Server로 직접 데이터를 선택하는 것입니다.

관련 문제