SQL Server에 sqlite 테이블을 복사하기 위해 데이터 테이블을 읽지 않고 C#으로 전환 할 수 있습니까?sqlite에서 SQL Server로 데이터 복사
sqlite 데이터베이스가 메모리에 있으며 수백만 개의 행을 포함하므로 절대적으로 필요한 경우가 아니라면 데이터 테이블에 복사하지 않으려합니다.
감사 KevCri
SQL Server에 sqlite 테이블을 복사하기 위해 데이터 테이블을 읽지 않고 C#으로 전환 할 수 있습니까?sqlite에서 SQL Server로 데이터 복사
sqlite 데이터베이스가 메모리에 있으며 수백만 개의 행을 포함하므로 절대적으로 필요한 경우가 아니라면 데이터 테이블에 복사하지 않으려합니다.
감사 KevCri
질문이 오래된 경우에도 나중에 참조 할 수 있도록 일부 소스 코드에 답하고 싶습니다. 나는 똑같은 문제점을 가지고 있었고이 게시물을 발견했다. 트릭을 수행 할 콘솔 애플리케이션을 만들었습니다. 뷰가 아닌 테이블에서만 작동하며 제한된 데이터 집합에서만 테스트했습니다. 그러나 이론적으로 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);
}
}
}
}
위대한 유틸리티 코드를 이용해 주셔서 감사합니다. 나는 단지 작은 문제 하나를 발견했다. 리버스 엔지니어링과 임포트를 위해 선택한 테이블이 필드 이름을 구분하는 '['대괄호를 가지지 않았기 때문에 여러분이 사용한 replace 문은 파울이되었습니다 ... 작은 변화 ...하지만 여전히 가치있는 코드 조각입니다. –
대괄호는 공백이 포함 된 열에서 주로 사용됩니다. 나는 SQLite 드라이버의 버전이 다른 테이블 스키마 (괄호의 유무와 상관없이)에서 출력 될 수 있다고 생각한다. – nivs1978
ODBC driver SQLite는 존재합니다. SSIS 설치에 액세스 할 수 있으면 데이터 가져 오기 작업을 사용하여 테이블을 가져올 수 있습니다. 더 쉬운 방법은 SQL Server 가져 오기/내보내기 마법사를 사용하는 것입니다.
또 다른 옵션은 SQLite 데이터베이스에 대한 ODBC DSN을 만든 다음 OPENROWSET을 사용하여 SQLite에서 SQL Server로 직접 데이터를 선택하는 것입니다.
[SqliteDataReader] (http://sqlite.phxsoftware.com/)를 사용하여 행을 반복 할 수 있습니다. – swasheck