MySQL 迁移至 SQLite 问题记录

Posted 御劍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 迁移至 SQLite 问题记录相关的知识,希望对你有一定的参考价值。

最近接手了一个WPF项目,数据库使用的MySQL,为了简化生产环境部署流程,果断选择迁移到SQLite,由于原项目未使用ORM框架,导致很多SQL语法也得改。

SQLite基础语法请参考该页面 

  1.依赖包的更改

    有两个Nuget包可选: Microsoft.Data.Sqlite.Core / System.Data.SQLite,我都安装试了下,除了类型大小写不一致之外,功能几乎一样,由于老项目是.Net Framework 4.x,稳妥起见还是使用了后者,至于各种引用类型的更改,几乎只需要将MySql开头的类型名全局替换成SQLite的则可(记得删掉MySQL的引用,确保只调用了SQLite相关类库)  

    

  

  2.数据库连接

    SQLite本身是一个基于文件的数据库系统,每个数据库就是一个文件,若文件不存在它会自动创建,下面的示例代码就是建立与运行目录下test.sqlite文件的连接     

  private const string connStr = "Data Source = 0";
  ...
  string dbName = "test.sqlite";   SQLiteConnection Connection
= new SQLiteConnection(string.Format(connStr, dbName));
  Connection.Open();

  

  3.数据库切换

    虽然SQLiteConnection也提供了ChangeDatabase方法,但是不管用 o(╥﹏╥)o   得先手动释放原来的连接资源,再建立新的连接

    Connection?.Dispose();
    Connection = new SQLiteConnection(string.Format(connStr, dbName));
    Connection.Open();

  

  4.建表差异

    编码集和数据引擎的部分肯定是不能要了,主键要将关键字放到对应字段后面,自增则是去掉下划线(大小写依然不敏感),但是有一个需要注意的地方是:自增字段得用integer,用int也行,但它不会自增

  private const string SQL_CreateTable = @"
                create table if not exists `TestTable` (
                    id int not null auto_increment,                    
                    name varchar(64) not null,
                    primary key(id),
            unique key(name) ) collate=\'utf8_general_ci\' engine=InnoDB;
";
  //上面是MySQL建表语句
  //下面是SQLite建表语句
  
private const string SQL_CreateTable = @" create table if not exists `TestTable` ( id integer PRIMARY KEY AUTOINCREMENT NOT NULL, name varchar(64) not null );";

 

 

  5.删表差异 - truncate 语句

    SQLite不支持 truncate ,清空一张表需要先delete,然后再去sqlite_sequence表里删除对应表名的自增键

  new SQLiteCommand(@"delete from tablename;", Connection).ExecuteNonQuery();
  new SQLiteCommand(@"DELETE FROM sqlite_sequence WHERE name = \'tablename\';", Connection).ExecuteNonQuery();

 

  6.数据类型差异

    MySqlDbType要更改为DbType,后者位于System.Data命名空间下,具体对照关系参考这个链接,图中的Key值为MySqlDbType类型,Value为对应的DbType类型

  

    

 

  7.逻辑操作符差异 -- &&符号

    若不是接手这个项目,我都不知道MySQL居然能用 && 操作符,SQLite当然是不支持的,得改成 and 关键字

 

  8.待补充,以后遇到其他问题再补充

sqlite迁移mysql的若干错误

sqlite迁移mysql报错Source data type [DATE] not supported

不论是用Navicat还是MySQL workbench,迁移时碰到表会遇到类似如下错误:

80120001: Source data type [DATE] not supported

大概意思就是数据源中某个字段的DATE型在目标数据库中不支持。

为解决这个问题,采用python的方案进行移植:

import sqlite3
import pandas as pd
from sqlalchemy import create_engine

srcconn = sqlite3.connect('src.db')
dstengine = create_engine('mysql+pymysql://user:pass@localhost/dstdb')

sqlstr = 'select * from tablename'
srcdf = pd.read_sql(sqlstr, srcconn)
srcdf.to_sql('tablename', dstengine, index=True)

以上方案能成功迁移表结构和数据,区别是是部分column的数据类型会改变,比如这里的DATE会被换成TEXT

迁移后group by性能下降

sqlite上在68k数据上处理两个field的group by只需要0.1s不到,但是新数据库中需要118s;

查资料发现可能是数据类型的问题:

[mysql]SQL语句性能优化--Group by中执行慢性能差的原因调查与处理_王德封-逐浪-CSDN博客

于是将TEXT类型换成varchar后,时间确实有明显缩短:0.3s

1406 - Data too long for column  at row 1

sqlite的text迁移到MySQL后,存储结构变化很大,严重影响查询性能,所以要将text类型转为varchar,而此处报错,是因为length没有填具体值,导致报错,填写后合适的length值后可正常保存表设计。

以上是关于MySQL 迁移至 SQLite 问题记录的主要内容,如果未能解决你的问题,请参考以下文章

开源社区行为准则风波不断,SQLite 遭批评;OpenJDK 源码计划迁移至 GitHub

初码-Azure系列-迁移PHP应用至Azure的一些实践记录和思考

数据从sqlite3迁移到mysql中遇到的问题

sqlite迁移mysql的若干错误

sqlite迁移mysql的若干错误

sqlite迁移mysql的若干错误