参考
SQLite官网
SQL As Understood By SQLite
System.Data.SQLite
菜鸟教程

章节

一、下载安装
这段时间在学习 C# 编程中,想写一个简单的进销存程序,就想到了用数据库,需要一个简单便携的桌面数据库,想自己写个,功力太浅,可以做为以后练手学习的项目。原来会用的 Foxpro 已经被微软不知丢在哪个旮旯了,在网上找了一下,发现只有 Access 和 Sqlite 可选,看了很多对比,决定还是学习使用 Sqlite。

在 System.Data.SQLite 官网的 download 中的 Setups for 64-bit Windows (.NET Framework 4.6) sqlite-netFx46-setup-x64-2015-1.0.104.0.exe (17.99 MiB) 下载然后运行安装。
更简单的做法是在 Visual Studio 2017 的 NuGet 中,输入:install-package system.data.sqlite.x64。

sqlite数据库的可视化工具中, SqliteExpert 不错,下载 SQLite Expert Personal 4.x 。

工具备齐了,由于知道上面这个System data Sqlite 是用 C# 封装好的,下来我们打开Visual Studio 2017,新开个工程,在菜单“项目”→“添加引用”→“浏览” 中,去 Sqlite 的安装目录下选择 System.Data.SQLite.dll,才305k的链接库。引用了后,在VS右上角的“解决方案资源管理器”中看看引用下的 System.Data.SQlite 的引用属性中的“复制到本地” 是不是 true,不是的话弄成 true。在工程中开头添加 using 语句:

using System.Data.SQLite;

网上很多教程到这就ok了,但在我实际操作中,发现还要把 SQLite.Interop.dll 也拷贝到当前程序运行目录下(不能引用,只能直接拷贝),不知道是不是新版本的要求。

(ps:在 sqlite 的安装目录下有很详细的帮助文档 SQLite.NET.chm)

二、数据类型
储存的数据类型有以下5种:

注意:SQLite 的存储宽度是根据输入来自动调整的,这点和原来我用过的 foxpro 不一样,比如就算你在 create 数据表中设定了一个字段 varchar(4) 4byte宽的字符串,但你输入了“hello”5个宽度的字符串时,它并不会截取成“hell”,而是完整地存储为“hello”。数字类型也是如此。

还有更有趣的是,它有个Type Affinity 功能,比如如下:

CREATE TABLE t1(a INT, b VARCHAR(10));
INSERT INTO t1(a,b) VALUES(‘123’,456);

它会运用 Type Affinity 功能自动正确地把 “123” 转换成数字,把 456转化成“456”字符串。这个Type Affinity 请参考安装目录下的 帮助文件或 SQLite 亲和(Affinity)类型。SQLite 亲和(Affinity)类型

三、创建数据库

SQLite 是文件型的数据库,创建很简单,直接指定一个数据库文件名,后缀名不一定非得是“.sqlite”,后缀随便命名为".db"也成。运行 SQLiteConnection.open 就会创建个空的指定名字的数据库文件。由于它是文件型的,我们也可以直接用 System.IO.File.Create() 来创建一个空的文件。

using System.Data.SQLite;
//---创建数据库
static void CreateDB()
{string path = @"d:\test\123.sqlite";SQLiteConnection cn = new SQLiteConnection("data source=" + path);cn.Open();cn.Close();
}

四、删除数据库
sqlite 命令中好像没有提供删除整个数据库的命令,但是由于它是个文件型的,我们直接用 System.IO.File.Delete(string path) 方法来删除文件。

//---删除数据库
static void DeleteDB()
{string path = @"d:\test\123.sqlite";if (System.IO.File.Exists(path)){System.IO.File.Delete(path);}
}

五、创建表
开始要用到 SQL 命令了。建立一个表的顺序如下步骤(也可以用可视化工具 SQLiteExpert 来创建):
1、建立数据库连接;
2、打开数据库(如果没有数据库,Open 也会新创建一个数据库);
3、声明一个 SQLiteCommand 类,主要用来放置和运行 SQL 命令的;
4、把 SQLiteCommand 的 Connection 和 SQLiteConnection 联系起来(切记,经常忘_!);
5、往 SQLiteCommand 的 CommandText 输入 SQL 语句 CREATE TABLE 语句,具体请参考 安装目录下的 SQLite.NET.chm 或 SQLite 创建表;
6、调用 SQLiteCommand.ExcuteNonQuery() 方法运行。

//---添加表
static void CreateTable()
{string path = @"d:\test\123.sqlite";SQLiteConnection cn = new SQLiteConnection("data source="+path);if (cn.State!= System.Data.ConnectionState.Open){cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;cmd.CommandText = "CREATE TABLE t1(id varchar(4),score int)";//cmd.CommandText = "CREATE TABLE IF NOT EXISTS t1(id varchar(4),score int)";cmd.ExecuteNonQuery();}cn.Close();
}

注意上面那句被注释掉的 CREATE TABEL IF NOT EXISTS ,一般情况下用这句比较好,如果原来就有同名的表,没有这句就会出错。SQL 语句其实也不用全部大写,全部大写是 SQL 语句约定俗成的(令我想起读书的时候学的 COBOL),全部小写也不会出错。

六、删除表

和建立表的步骤一样,只是把 SQL 语句改了而已。//---删除表
static void DeleteTable()
{string path = @"d:\test\123.sqlite";SQLiteConnection cn = new SQLiteConnection("data source=" + path);if (cn.State != System.Data.ConnectionState.Open){cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;cmd.CommandText = "DROP TABLE IF EXISTS t1";cmd.ExecuteNonQuery();}cn.Close();
}

七、查询表结构
需要用到 SQLite 特殊的 PRAGMA 命令, 具体参见 PRAGMA Statements
PRAGMA table_info(tablename) ,tablename 用或不用单引号 ’ ’ 括起来都一样。
SQliteDataReader 读出来的数据顺序代表:

string path = @"d:\test\123.sqlite";
SQLiteConnection cn = new SQLiteConnection("data source=" + path);
cn.Open();
SQLiteCommand cmd = cn.CreateCommand();cmd.CommandText= "PRAGMA table_info('t1')";//写法一:用DataAdapter和DataTable类,记得要 using System.Data
SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd);
DataTable table = new DataTable();
adapter.Fill(table);
foreach(DataRow r in table.Rows)
{Console.WriteLine($"{r["cid"]},{r["name"]},{r["type"]},{r["notnull"]},{r["dflt_value"]},{r["pk"]} ");
}
Console.WriteLine();//写法二:用DataReader,这个效率高些
SQLiteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{for(int i = 0; i < reader.FieldCount; i++){Console.Write($"{reader[i]},");}Console.WriteLine();
}
reader.Close();

如果不止一个表,要遍历所有表的结构如下,就要用到 SQLite 中的特殊表 sqlite_master,它的结构如下:2.6. Storage Of The SQL Database Schema

CREATE TABLE sqlite_master(
type text,
name text,
tbl_name text,
rootpage integer,
sql text
);
//当 type = table 时,name 和 tbl_name 是一样的,其他比如 type =index 、view 之类时,tbl_name 才是表名。
//---遍历查询表结构
static void QueryAllTableInfo()
{string path = @"d:\test\123.sqlite";SQLiteConnection cn = new SQLiteConnection("data source=" + path);if (cn.State != System.Data.ConnectionState.Open){cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;cmd.CommandText = "SELECT name FROM sqlite_master WHERE TYPE='table' ";SQLiteDataReader sr = cmd.ExecuteReader();List<string> tables = new List<string>();while (sr.Read()){tables.Add(sr.GetString(0));}//datareader 必须要先关闭,否则 commandText 不能赋值sr.Close();foreach (var a in tables){cmd.CommandText = $"PRAGMA TABLE_INFO({a})";sr = cmd.ExecuteReader();while (sr.Read()){Console.WriteLine($"{sr[0]} {sr[1]} {sr[2]} {sr[3]}");}sr.Close();}}cn.Close();
}

八、更改表名

//用 SQL 语句 ALTER TABLE 把 t1 表名改成 t3:cmd.CommandText = "ALTER TABLE t1 RENAME TO t3";
cmd.ExecuteNonQuery();
//注意,表名是不分大小写的,也不用加单引号括起来。

九、增添列(字段)

//还是用 SQL 命令 ALTER TABLE ,下例中为 t1 表添加一个名为 age,数据类型为 int 的新列:cmd.CommandText = "ALTER TABLE t1 ADD COLUMN age int";
cmd.ExecuteNonQuery();

十、读取创建表的 SQL 语句

//读取创建表时的 SQL 语句,在 SqliteExpert 中的 DDL 可以查看到。读取这个是为下面增添删除列做准备。cmd.CommandText = "SELECT sql FROM sqlite_master WHERE TYPE='table'";
SQLiteDataReader sr = cmd.ExecuteReader();
while (sr.Read())
{Console.WriteLine(sr[0].ToString());
}
sr.Close();

十一、更改列名
SQLite 中并没有提供直接更改列名与删除列的命令,有两种方式,
第一种是:
1、把目标表改名;
2、创建一个带有新列名的新表;
3、把旧表数据拷贝至新表(记得要 Connection.BeginTransaction())。

第二种是更改 sqlite_master 里面的 schema,很容易损坏数据库。
依据是 SQLite 每次连接时,其实都是依据 schema 里面的每个表创建时的 CREATE TABLE 语句来动态建立 column 的信息的,只要 column 的数据类型和位置不变,更改 CREATE TABLE 语句就能更改 column 的信息。具体参考 How do I rename a column in a SQLite database table?。以下我们两种方法都写来看看。

方式一:

//---更改列名1
//总思路:把旧表更名,建个带新列名的新表,拷贝数据
//params string[] 中:0 数据库名,1 表名,2 旧列名 3 新列名
static void RenameColumn1(params string[] str)
{SQLiteConnection cn = new SQLiteConnection("data source=" + str[0]);cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;//取得str[1]表名的表的建表SQL语句 cmd.CommandText = "SELECT name,sql FROM sqlite_master WHERE TYPE='table' ORDER BY name";SQLiteDataReader sr = cmd.ExecuteReader();string _sql = ""; while (sr.Read()){if (string.Compare(sr.GetString(0), str[1], true) == 0){_sql = sr.GetString(1);break;}}sr.Close();//更改旧表名为 带 _old string _old = str[1] + "_old";cmd.CommandText = $"ALTER TABLE {str[1]} RENAME TO {_old}";cmd.ExecuteNonQuery();//建立新表,假设输入的旧列名和表中的列名大小写等完全一致,不写能容错的了_sql = _sql.Replace(str[2],str[3]);cmd.CommandText = _sql;cmd.ExecuteNonQuery();//拷贝数据using (SQLiteTransaction tr = cn.BeginTransaction()){cmd.CommandText = $"INSERT INTO {str[1]} SELECT * FROM {_old}";cmd.ExecuteNonQuery();cmd.CommandText = $"DROP TABLE {_old}";cmd.ExecuteNonQuery();tr.Commit();}cn.Close();
}

方式二:

//---更改列名2,改写schema里建表时的sql语句
//原理:sqlite 每次打开的时候,都是依据建表时的sql语句来动态建立column的信息的
static void RenameColumn2(params string[] str)
{SQLiteConnection cn = new SQLiteConnection("data source=" + str[0]);cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;//取得str[1]表名的表的建表SQL语句 cmd.CommandText = $"SELECT sql FROM sqlite_master WHERE TYPE='table' AND name='{str[1]}'";SQLiteDataReader sr = cmd.ExecuteReader();sr.Read();string _sql = sr.GetString(0);sr.Close();//注意单引号 '_sql =$"UPDATE sqlite_master SET sql='{_sql.Replace(str[2],str[3])}' WHERE name= '{str[1]}' ";//设置 writable_schema 为 true,准备改写schema cmd.CommandText = "pragma writable_schema=1";cmd.ExecuteNonQuery();cmd.CommandText = _sql;cmd.ExecuteNonQuery();//设置 writable_schema 为 false。cmd.CommandText = "pragma writable_schema=0";cmd.ExecuteNonQuery();cn.Close();
}十二、删除列SQLite 也没有提供删除列的命令。和上面一样,也是两种方式。
其一,把目标表改名,建立没有要删除列(字段)的新表,然后把旧表的数据拷贝至新表。
其二,直接修改 schema 中建表的 SQL 语句。
其中最主要的是要把建表的列的所有信息都保存下来,比如索引、缺省值之类的。下面示例使用第二种方式。//---删除列2,string[] ,0 数据库路径,1 表名,2 要删除的列名
static void DeleteColumn2(params string[] str)
{SQLiteConnection cn = new SQLiteConnection("data source=" + str[0]);cn.Open();SQLiteCommand cmd = new SQLiteCommand();cmd.Connection = cn;//取得str[1]表名的表的建表SQL语句 cmd.CommandText = $"SELECT sql FROM sqlite_master WHERE TYPE='table' AND name='{str[1]}'";SQLiteDataReader sr = cmd.ExecuteReader();sr.Read();string _sql = sr.GetString(0);sr.Close();//取得列的定义//C#7.0的新特征,Tuple<>的语法糖,需要 NuGet install-package system.valuetupleList<(string name, string define)> list = GetColumnDefine(_sql);//取得要删除列的序号int _index = list.IndexOf(list.Where(x => x.name == str[2]).First());//建立新的sql语句StringBuilder sb = new StringBuilder();sb.Append($"CREATE TABLE {str[1]}(");for (int i = 0; i < list.Count; i++){if (i != _index){sb.Append($"{list[i].define},");}}sb.Remove(sb.Length - 1, 1);sb.Append(")");//改写schema_sql = $"UPDATE sqlite_master SET sql='{sb.ToString()}' WHERE name='{str[1]}'";//设置 writable_schema 为 true,准备改写schema cmd.CommandText = "pragma writable_schema=1";cmd.ExecuteNonQuery();cmd.CommandText = _sql;cmd.ExecuteNonQuery();//设置 writable_schema 为 false。cmd.CommandText = "pragma writable_schema=0";cmd.ExecuteNonQuery();cn.Close();
}
//---取得列的定义
static List<(string, string)> GetColumnDefine(string SqlStr)
{int n = 0;int _start = 0;string _columnStr = "";for (int i = 0; i < SqlStr.Length; i++){if (SqlStr[i] == '('){if (n++ == 0) { _start = i; }}else{if (SqlStr[i] == ')'){if (--n == 0){_columnStr = SqlStr.Substring(_start + 1, i - _start - 1);break;}}}}string[] ss = _columnStr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);//C#7.0的新特征,Tuple<>的语法糖,需要 NuGet install-package system.valuetupleList<(string name, string define)> reslut = new List<(string name, string define)>();foreach (var a in ss){string s = a.Trim();n = 0;for (int i = 0; i < s.Length; i++){if (s[i] == ' '){reslut.Add((s.Substring(0, i), s));break;}}}return reslut;
}

十三、插入数据
插入数据主要是用 SQL 语句 INSERT INTO
//示例1(简单插入):

cmd.CommandText = "INSERT INTO t1 VALUES('99999',11)";
cmd.ExecuteNonQuery();

//示例2(变量插入,要引用 System.Data):

using System.Data;string s = "123456";
int n = 10;
cmd.CommandText = "INSERT INTO t1(id,age) VALUES(@id,@age)";
cmd.Parameters.Add("id", DbType.String).Value = s;
cmd.Parameters.Add("age", DbType.Int32).Value = n;
cmd.ExecuteNonQuery();

十四、替换数据
SQL 命令 INSERT INTO。
下面示例中, t1 表中 id 为主键,相同主键值的就 UPDATE,否则就 INSERT

string s = "123456";
int n = 30;
cmd.CommandText = "REPLACE INTO t1(id,age) VALUES(@id,@age)";
cmd.Parameters.Add("id", DbType.String).Value = s;
cmd.Parameters.Add("age", DbType.Int32).Value = n;
cmd.ExecuteNonQuery();

十五、更新数据
SQL 命令 UPDATE tablename SET column1=value,column2=value… WHERE 条件


string s = "333444";
int n = 30;
cmd.CommandText = "UPDATE t1 SET id=@id,age=@age WHERE id='0123456789'";
cmd.Parameters.Add("id", DbType.String).Value = s;
cmd.Parameters.Add("age", DbType.Int32).Value = n;
cmd.ExecuteNonQuery();

十六、删除数据

SQL 命令:DELETE FROM tablename WHERE 条件

cmd.CommandText = "DELETE FROM t1 WHERE id='99999'";
cmd.ExecuteNonQuery();

十七、查询数据

SQL 命令:SELETE 语句,具体的请参考 SQL 教程。

//查询第1条记录,这个并不保险,rowid 并不是连续的,只是和当时插入有关
cmd.CommandText = "SELECT * FROM t1 WHERE rowid=1";
SQLiteDataReader sr = cmd.ExecuteReader();
while (sr.Read())
{Console.WriteLine($"{sr.GetString(0)} {sr.GetInt32(1).ToString()}");
}
sr.Close();
//运行以下的就能知道 rowid 并不能代表 行数
cmd.CommandText = "SELECT rowid FROM t1 ";
sr = cmd.ExecuteReader();
while (sr.Read())
{Console.WriteLine($"{sr.GetString(0)} {sr.GetInt32(1).ToString()}");
}
sr.Close();

十八、获取查询数据的行数(多少条记录)
从上面示例中我们得知,rowid 并不是正确的行数(记录数),而是 INSERT 的时候的B-Tree 的相关数。
如要知道表中的行数(记录数),要如下:

cmd.CommandText = "SELECT count(*) FROM t1";
sr = cmd.ExecuteReader();
sr.Read();
Console.WriteLine(sr.GetInt32(0).ToString());
sr.Close();

十九、事务
事务就是对数据库一组按逻辑顺序操作的执行单元。用事务的好处就是成熟的数据库都对 密集型的磁盘 IO 操作之类进行优化,而且还能进行撤回回滚操作。其实在上面改变列名的示例中就用过。

//---事务
static void TransActionOperate(SQLiteConnection cn,SQLiteCommand cmd)
{using (SQLiteTransaction tr = cn.BeginTransaction()) {string s = "";int n = 0;cmd.CommandText = "INSERT INTO t2(id,score) VALUES(@id,@score)";cmd.Parameters.Add("id", DbType.String);cmd.Parameters.Add("score", DbType.Int32);for (int i = 0; i < 10; i++){s = i.ToString();n = i;cmd.Parameters[0].Value = s;cmd.Parameters[1].Value = n;cmd.ExecuteNonQuery();}tr.Commit();}
}

二十、整理数据库

SQLite 的自带命令 VACUUM。用来重新整理整个数据库达到紧凑之用,比如把删除的彻底删掉等等。

cmd.CommandText = "VACUUM";
cmd.ExecuteNonQuery();

说明:以上借鉴资源地址为https://www.cnblogs.com/leemano/p/6578050.html#c1
若侵权联系可删。

【示例demo】
以下是自己操作时的源码,作为记录使用了以下dll,下载地址:

//插入数据
string StrConnect=@"Data Source=.\DataBase.s3db;Initial Catalog=sqlite;Integrated Security=True;Max Pool Size=10";//数据库地址
var connection = new SQLiteConnection(StrConnect);//数据库连接var compiler = new QueryBuilder.Compilers.SqliteCompiler();var db1 = new QueryFactory(connection, compiler);connection.Open();//打开IDbTransaction trans = db1.Connection.BeginTransaction();try{ var query = db1.Query(tableName);foreach (var item in pList){query.Insert(new{ID = item.ID,BDCDYH = item.BDCDYH,ZDDM=item.ZDDM}, trans);trans.Commit();//提交}catch (Exception ex){trans.Rollback();//回滚}finally{connection.Close();//关闭数据库连接}

Sqlite数据库操作综合及相关推荐

  1. 实验8 SQLite数据库操作

    实验报告 课程名称 基于Android平台移动互联网开发 实验日期 2016/5/6 实验项目名称 SQLite数据库操作 实验地点 综合实验室 实验类型 □验证型    √设计型    □综合型 学 ...

  2. 数据存储之 SQLite 数据库操作(三)

    上一讲中我们讲到了SQLite数据库的操作方法 [数据存储之SQLite数据库操作(二)],我们主要是以SQL语句对数据库进行增删改查,这一讲我们来学习一下 Android 建议的对数据库的操作方法 ...

  3. 数据存储之 SQLite 数据库操作(二)

    上一讲我们讲解了SQLite数据库的创建[数据存储之 SQLite 数据库操作(一)],还有更新的操作,这一讲我们来讲解一下数据库的增删改查,这边的程序是对上一个程序进行修改,建议结合上一讲内容进行学 ...

  4. Qt下Sqlite数据库操作

    Sqlite数据库作为Qt项目开发中经常使用的一个轻量级的数据库,可以说是兼容性相对比较好的数据库之一(Sqlite就像Qt的亲儿子,如同微软兼容Access数据库一样).关于Sqlite和Qt的千丝 ...

  5. C# SQLite 数据库操作语句与文件视图管理器

    //sqlite数据库视图管理器 SQLiteSpy是一款专业的SQLite数据库管理,主要用于读取sqlite数据库,建立新的SQL查询,视图,复制和删除表.编辑单元格,以及查看索引,触发器和排序规 ...

  6. java sqlite 操作_Java SQLite 数据库操作

    Java SQLite 数据库操作 1.[代码][Java]代码 package UI; import java.sql.Connection; import java.sql.DriverManag ...

  7. Android sqlite数据库操作通用框架AHibernate(一)-CRUD示例和使用步骤

    AHibernate简介 一句话描述,使用AHibernate框架进行sqlite数据库操作您将从重复性劳动中解脱出来. (一)支持功能: 1.自动建表,支持属性来自继承类:可根据注解自动完成建表,并 ...

  8. SQLite数据库操作实践

    SQLite数据库操作实践 SQLite存储类型 null       - 空值  integer - 有符号整数,自增列定义 id integer primary key autoincrement ...

  9. SQLite数据库操作+事务处理

    SQLite数据库操作 SQLite数据库介绍 Android系统中集成的轻量级的数据库 特点: 轻量级 是以单个文件的形式进行存取 跨平台 支持多个操作系统 零配置 无需安装, 直接使用 嵌入式 内 ...

最新文章

  1. GPU端到端目标检测YOLOV3全过程(上)
  2. iOS 多线程的四种技术方案
  3. php t double arrow,关于php:php – 语法错误,意外T_DOUBLE_ARROW
  4. 一文攻破共用体-C语言
  5. Spring Boot——统一设置返回Json数据风格(Java驼峰命名法转下划线命名法)解决方案
  6. 全国计算机一级d类考试内容,全国计算机一级考试WPS office复习题及答案2017
  7. 【SSH网上商城项目实战05】完成数据库的级联查询和分页
  8. HDU4859 海岸线(最小割)
  9. 如何删掉oracle服务,oracle留下的服务如何删除啊
  10. 计算机内存外存共同点,存储器:内存和外存
  11. PS—制作 抖音 图标
  12. 三亚适合几月份去玩 三亚必去的地方是哪里
  13. node nvm 安装及使用
  14. 单源最短路径dijkstra算法
  15. js中正则表达式的应用
  16. QUARTZ 简单介绍
  17. 使用Python+Opencv+Flask将windows端的摄像头变为网络摄像头的方法
  18. HTML个人简历表制作
  19. idea下设置git忽略提交ignore
  20. HBuilder X 下载安装内置浏览器失败

热门文章

  1. Java 线程创建方法之一——实现Runnable接口、匿名内部类写法
  2. jsp和servlet的区别
  3. matlab实现盖尔圆,一种结合四阶累积量与盖尔圆改进的信号源个数估计方法与流程...
  4. 易语言ftp服务器管理器,易语言ftp服务器源码
  5. 对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值。对于一个整数,从个位开始对每一位数字编号,个位是1号,十位是2号,以此类推。这个整数在第n位上的数字记作x,如果x和n的奇偶性相同,则记下一
  6. 猪肉概念股上涨的思考
  7. 干货 :深入浅出神经网络的改进方法!
  8. Ubuntu 14.04 LTS 英文环境下中文字体修改
  9. 2021-05-16 C#.NET面试题 什么是虚函数?什么是抽象函数?
  10. The interview