IT/C#

[C#] MySQL to SQLite Converter

Ella.J 2021. 3. 25. 14:06
728x90
반응형

MySQL 데이터베이스에서 사용하고 있던 데이터들을 SQLite 데이터베이스로 변경하기 위해

컨버터 프로그램을 만들어 봤습니다.

C# WinForm을 이용해서 만들었으며, 아래의 프로그램은 MySQL DB만 SQLite DB로 변경가능하지만,

코드를 작성하고나면 반대의 경우도 만들 수 있을 것이라 예상됩니다 *^^*


메인 Form 디자인은 다음과 같습니다.


먼저 MySql 연결을 위해서는 Database 이름, 사용자 ID, Password, 그리고 Server 입력이
필요하기 때문에 TextBox 4개로 입력을 받고, Connect 버튼을 만들어 버튼 이벤트를 연동시켜
MySql에 연결하도록 했으며,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void btnConnect_Click(object sender, EventArgs e)
{
    //TextBox에 입력된 데이터베이스 연결
    if(_mysql.Connection(txtServer.Text, txtUserID.Text, txtPWS.Text, txtDB.Text))
    {
        Log("MySql Connection Successed.");
 
        //현재 데이터베이스에 존재하는 테이블 목록 가져오기
        DataSet ds = _mysql.SendQuery("show TABLES");
        cbTable.Items.Clear();
        foreach (DataRow dr in ds.Tables[0].Rows)
        {
            string table = dr[$"tables_in_{txtDB.Text}"].ToString();
            cbTable.Items.Add(table);
        }
        if (cbTable.Items.Count > 0) cbTable.SelectedIndex = 0;
    } else
    {
        Log("MySql Connection Failed.");
    }
}
cs

Log TextBox에는 연결상태 및 SQLite로 변경 시 로그가 남도록 했습니다.

1
2
3
4
public void Log(string log)
{
    txtLog.AppendText(log + "\r\n");
}
cs

MySql에 연결하면 오른쪽에 있는 Browse Data 아래의 현재 DB의 테이블 리스트가 ComboBox에 추가되며, 

테이블 선택시 왼쪽 아래에는 테이블 생성 쿼리, 오른쪽에는 테이블 데이터를 볼 수 있도록 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
private void cbMySqlTable_SelectedIndexChanged(object sender, EventArgs e)
{
    //선택된 테이블의 모든 레코드 읽기
    DataSet ds = _mysql.SendQuery("SELECT * FROM " + cbTable.Text);
    dgvTable.DataSource = ds.Tables[0];
 
    //선택된 테이블 생성 쿼리 가져오기
    DataSet dst = _mysql.SendQuery($"Show CREATE TABLE {cbTable.Text}");
    foreach (DataRow dr in dst.Tables[0].Rows)
    {
        txtTableQuery.Text = dr["CREATE TABLE"].ToString();
    }
}
cs

연결한 MySql Database의 테이블 생성 쿼리와 데이터들을 확인하여
맨 오른쪽의 Convert All to SQLite 버튼을 누르면 데이터를 옮기도록 했으며,
SQLite는 {db_name}.db 의 확장자를 가진 파일로 버튼 클릭 이벤트에서
SaveFileDialog를 호출하여 폴더와 파일이름을 지정 후 데이터를 옮길 수 있게 했습니다.


SQLite의 데이터 타입은 5가지(NULL, INTEGER, REAL, TEXT, BLOB) 뿐이지만,
다른 DB에서 사용하는 데이터 이름 그대로 사용해도 문제가 없기 때문에,
MySql에서 테이블을 생성했던 쿼리를 그대로 사용해서 테이블을 만들도록 했습니다.


MySQL에서 테이블 생성 쿼리(SHOW CREATE TABLE {table_name})를 확인할 수 있기 때문에
컬럼명, 컬럼타입 등을 확인할 수 있어, 데이터타입을 확인하여 SQLite 데이터 입력시에
구분하여 입력가능하도록 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
private void btnMysql2Sqlite_Click(object sender, EventArgs e)
{
    SaveFileDialog sfd = new SaveFileDialog();
    if (sfd.ShowDialog() == DialogResult.OK)
    {
        //생성할 SQLite 파일 경로 가져오기
        _sqlite.DBPath = sfd.FileName;
        if (cbTable.Items.Count > 0)
        {
            //현재 데이터베이스에 존재하는 테이블만큼 반복
            for (int i = 0; i < cbTable.Items.Count; i++//Table Create & Data Move
            {
                string table = cbTable.Items[i].ToString();
 
                DataSet dst = _mysql.SendQuery($"Show CREATE TABLE {table}");
                foreach (DataRow dr in dst.Tables[0].Rows)
                {
                    //테이블 생성 쿼리 이용하여 SQLite 테이블 생성
                    //SQLite의 데이터 타입은 5가지 유형(NULL, INTEGER, REAL, TEXT, BLOB)이 있지만,
                    //다른 DB에서 사용하는 데이터 이름 그대로 사용해도 문제가 없음
                    string tableQuery = dr["CREATE TABLE"].ToString();
                    int index = tableQuery.IndexOf("ENGINE");
                    tableQuery = tableQuery.Substring(0, index);
 
                    if (_sqlite.CreateTable(tableQuery))
                    {
                        Log($"'{table}' Table Creation Successed.");
                    }
                    else
                    {
                        Log($"'{table}' Table Already Exist.");
                    }
                    
                    //테이블 생성 쿼리에서 컬럼데이터만 가져오기
                    string[] column = tableQuery.Split('\n');
                    column = column.Where(x => x != column[column.Length - 1]).ToArray();
                    column = column.Where(x => x != column[0]).ToArray();
 
                    //현재 테이블 row 가져와서 SQLite에 입력하기
                    DataSet ds = _mysql.SendQuery("SELECT * FROM " + table);
                    dgvTable.DataSource = ds.Tables[0];
 
                    if (dgvTable.Rows.Count > 0)
                    {
                        for (int j = 0; j < dgvTable.Rows.Count; j++)
                        {
                            string value = ""//테이블 row 입력 쿼리
                            for (int k = 0; k < dgvTable.ColumnCount; k++)
                            {
                                //컬럼별 데이터 타입 가져오기
                                string[] columnData = column[k].Split(' ');
                                if (columnData[3].Contains("int")) //컬럼이 int인 경우
                                {
                                    value = value + $"{dgvTable.Rows[j].Cells[k].Value}, ";
                                }
                                else if (columnData[3].Contains("date")) //컬럼이 date인 경우
                                {
                                    DateTime dt = DateTime.Parse(dgvTable.Rows[j].Cells[k].Value.ToString());
                                    string date = dt.ToString("yyyy-MM-dd");
                                    value = value + $"'{date}', ";
                                }
                                else //컬럼이 다른 타입(text)인 경우
                                {
                                    value = value + $"'{dgvTable.Rows[j].Cells[k].Value}', ";
                                }
                            }
                            value = value.Substring(0, value.Length - 2);
                            //row 입력하기
                            _sqlite.Insert(table, value);
                        }
                        Log($"'{table}' Data Moved from MySql.");
                    }
                }
            }
            Log("Finished.");
        } else
        {
            Log("Table is not existed.");
        }
    }
}
cs

모든 테이블 생성 및 데이터 변환이 끝나면 로그창에 Finished. 를 확인할 수 있습니다.
생성된 {db_name}.db 파일을 DB Browser for SQLite 프로그램을 통하여 확인한 결과는
아래 사진으로 첨부하였습니다.

데이터가 잘 옮겨진 것을 확인할 수 있습니다 : )

각각의 MySQL 클래스와 SQLite 클래스는 아래에 코드로 첨부하며,
전체 소스는 맨 하단의 링크로 확인하실 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class MySql
{
    MySqlConnection conn;
    MySqlDataAdapter adpt;
    MySqlCommand cmd;
 
    public bool Connection(string server, string id, string pwd, string db)
    {
        try
        {
            conn = new MySqlConnection($"server={server};uid={id};pwd={pwd};database={db};pooling=false;allow user variables=true");
            conn.Open();
            conn.Close();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
            return false;
        }
    }
 
    public DataSet SendQuery(string sql)
    {
        try
        {
            DataSet ds = new DataSet();
            adpt = new MySqlDataAdapter(sql, conn);
            adpt.Fill(ds);
            if (ds.Tables.Count > 0return ds;
            else return null;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
            throw;
        }
    }
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class SQLite
{
    public string DBPath;
    public string dataSource;
 
    public bool CreateTable(string sql)
    {
        try
        {
            dataSource = $@"Data Source={DBPath};Version=3";
            if (!System.IO.File.Exists(DBPath))
            {
                SQLiteConnection.CreateFile(DBPath);
            }
 
            SQLiteConnection sqliteConn = new SQLiteConnection(dataSource);
            sqliteConn.Open();
            SQLiteCommand cmd = new SQLiteCommand(sql, sqliteConn);
            cmd.ExecuteNonQuery();
            sqliteConn.Close();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
            return false;
        }
    }
 
    public void Insert(string table, string value)
    {
        try
        {
            dataSource = $@"Data Source={DBPath}";
            using (SQLiteConnection conn = new SQLiteConnection(dataSource))
            {
                conn.Open();
                string sql = $"INSERT INTO {table} VALUES ({value})";
                SQLiteCommand cmd = new SQLiteCommand(sql, conn);
                cmd.ExecuteNonQuery();
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
            throw;
        }
    }
}
cs

전체 소스 코드 보러가기 :-)

https://bitbucket.org/JUNGKUMYEONG/mysql2sqlite/src/master/

 

Bitbucket

 

bitbucket.org

 

728x90
반응형