SQLite的使用
SQLite介绍
最近做一个数控系统的项目,winCE嵌入式操作系统+.Net Compact Framework环境+VS2008开发平台,开发的设备程序部署到winCE系统下的设备中运行。。
SQLite,是一款开源轻型的文件型数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
(ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。)
工作原理
不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
Windows上使用sqlite
2、创建数据库
插入数据:
INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Paul', 32, 'California', 20000.00 );
显示数据(前两个命令被用来设置正确格式化的输出)
sqlite>.header on
sqlite>.mode column
sqlite> SELECT * FROM COMPANY;
使用.NET操作SQLLITE
先下载ADO.NET2.0 Provider for SQLite。下载binarieszip版就可以了。下载完后解压缩,可以在bin目录下找到System.Data.SQLite.DLL。
在vs2008中用Add Reference(添加引用)功能把System.Data.SQLite.DLL加到工程里就可以了。
运行下面代码试试:
由于SQLite是个文件型 数据库,判断机器中是否有某个数据库,直接判断是否有此文件即可。
1、如果存在,
if (System.IO.File.Exists("\\Hard Disk\\PressBreak.db3")) { cnn = new SQLiteConnection(); cnn.ConnectionString = "Data Source = \\Hard Disk\\PressBreak.db3;Password = Sunkz"; cnn.Open(); return true; }
2、如果不存在
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//创建一个数据库文件 string datasource = "\\Hard Disk\\PressBreak.db3"; System.Data.SQLite.SQLiteConnection.CreateFile(datasource); //连接数据库 cnn = new SQLiteConnection(); cnn.ConnectionString = "Data Source = \\Hard Disk\\PressBreak.db3;Password = Sunkz";//设置密码,SQLiteADO.NET实现了数据库密码保护 cnn.Open(); System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand(); //创建表 string sql = "CREATE TABLE test(username varchar(20),password varchar(20))"; cmd.CommandText = sql; cmd.Connection = conn; cmd.ExecuteNonQuery(); //插入数据 sql = "INSERT INTO test VALUES('a','b')"; cmd.CommandText = sql; cmd.ExecuteNonQuery(); //或者: InsertSql="INSERT INTO PunchData(Id,Height, Angle, Radius, Strength) VALUES('{0}',{1},{2},{3},{4})"; cmd.CommandText=string.Format(InsertSql, punchData .Id , punchData.height.ToString(), punchData.angle.ToString(), punchData.radius.ToString(), punchData.strength.ToString()); cmd.ExecuteNonQuery(); //此处注意,单引号的使用,字段为字符串类型的话,要加单引号。 //取出数据 sql = "SELECT * FROM test"; cmd.CommandText = sql; System.Data.SQLite.SQLiteDataReader reader =cmd.ExecuteReader(); StringBuilder sb = new StringBuilder(); while (reader.Read()) { sb.Append("username:").Append(reader.GetString(0)).Append("\n") .Append("password:").Append(reader.GetString(1)); } MessageBox.Show(sb.ToString());
另附SQLite学习网站:http://www.w3cschool.cc/sqlite/sqlite-intro.html
SQLite错误代码整理
SQLite语句一定要严格按例子来写,例如:
"CREATE TABLE PunchData (Id Text primary key, Height Float, Angle Float, Radius Float, Strength Float)";
"INSERT INTO PunchData(Id,Height, Angle, Radius, Strength) VALUES('{0}',{1},{2},{3},{4})";
创建的时候Id是Text类型,插入的时候,{0}要加单引号。。 否则,Id为0123是,通过数据库操作 读取出来后变为123了。
最下面是执行SQLite语句的时候,若出错,出错对应的ErrorCode和Message。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
try { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = string.Format(punchInsertStr, punchData.id, punchData.height.ToString(), punchData.angle.ToString(), punchData.radius.ToString(), punchData.strength.ToString()); count = cmd.ExecuteNonQuery(); } } catch (SQLiteException ex) { int errorCode = (int)ex.ErrorCode; } //定义错误代码与相应的错误信息 public readonly Dictionary<int, string> errorMessage = new Dictionary<int, string> { { 1, "SQL错误或丢失数据库" }, { 2, "SQLite 内部逻辑错误" }, { 3, "拒绝访问" }, { 4, "回调函数请求取消操作" }, { 5, "数据库文件被锁定" } ,{ 19, "由于约束违例, 例如编号唯一" }}; //界面上调用 ,返回错误信息 string ErrorMassage = errorMessage[errorCode];
附:
#define SQLITE_OK 0 /* 成功 | Successful result */
/* 错误码开始 */
#define SQLITE_ERROR 1 /* SQL错误 或 丢失数据库 | SQL error or missing database */
#define SQLITE_INTERNAL 2 /* SQLite 内部逻辑错误 | Internal logic error in SQLite */
#define SQLITE_PERM 3 /* 拒绝访问 | Access permission denied */
#define SQLITE_ABORT 4 /* 回调函数请求取消操作 | Callback routine requested an abort */
#define SQLITE_BUSY 5 /* 数据库文件被锁定 | The database file is locked */
#define SQLITE_LOCKED 6 /* 数据库中的一个表被锁定 | A table in the database is locked */
#define SQLITE_NOMEM 7 /* 某次 malloc() 函数调用失败 | A malloc() failed */
#define SQLITE_READONLY 8 /* 尝试写入一个只读数据库 | Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* 操作被 sqlite3_interupt() 函数中断 | Operation terminated by sqlite3_interrupt() */
#define SQLITE_IOERR 10 /* 发生某些磁盘 I/O 错误 | Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* 数据库磁盘映像不正确 | The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* sqlite3_file_control() 中出现未知操作数 | Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL 13 /* 因为数据库满导致插入失败 | Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* 无法打开数据库文件 | Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* 数据库锁定协议错误 | Database lock protocol error */
#define SQLITE_EMPTY 16 /* 数据库为空 | Database is empty */
#define SQLITE_SCHEMA 17 /* 数据结构发生改变 | The database schema changed */
#define SQLITE_TOOBIG 18 /* 字符串或二进制数据超过大小限制 | String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* 由于约束违例而取消 | Abort due to constraint violation */ (例如:主键约束)
#define SQLITE_MISMATCH 20 /* 数据类型不匹配 | Data type mismatch */
#define SQLITE_MISUSE 21 /* 不正确的库使用 | Library used incorrectly */
#define SQLITE_NOLFS 22 /* 使用了操作系统不支持的功能 | Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* 授权失败 | Authorization denied */
#define SQLITE_FORMAT 24 /* 附加数据库格式错误 | Auxiliary database format error */
#define SQLITE_RANGE 25 /* 传递给sqlite3_bind()的第二个参数超出范围 | 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* 被打开的文件不是一个数据库文件 | File opened that is not a database file */
#define SQLITE_ROW 100 /* sqlite3_step() 已经产生一个行结果 | sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step() 完成执行操作 | sqlite3_step() has finished executing */
/* 错误码结束 */
学习资源
1、官网
2、专栏:sqlite入门教程 sqlite
3、工匠若水
Sqlite数据类型
SQLite数据类型是一个用来指定任何对象的数据类型的属性。SQLite 中的每一列,每个变量和表达式都有相关的数据类型。您可以在创建表的同时使用这些数据类型。SQLite使用一个更普遍的动态类型系统。在SQLite中,值的数据类型与值本身是相关的,而不是与它的容器相关。
SQLite有5个原始的数据类型,被称为存储类。存储类这个词表明了一个值在磁盘上存储的格式,其实就是类型或数据类型的同义词。如下即是存储类:
存储类 | Description |
---|---|
NULL | 值是一个NULL值。 |
INTEGER | 值是一个带符号的整数,根据值的大小存储在1、2、3、4、6 或8字节中。 |
REAL | 值是一个浮点值,存储为8字节的IEEE浮点数字。 |
TEXT | 值是一个文本字符串,使用数据库编码(UTF-8、UTF-16BE或UTF-16LE)存储。 |
BLOB | 值是一个blob数据,完全根据它的输入存储。 |
具有不同存储类的值可以存储在同一个字段中。可以被排序,因为这些值可以相互比较。有完善定义的规则来做这件事。不同存储类的值可以通过它们各自类的“类值”进行排序,定义如下:
- NULL存储类具有最低的类值。一个具有NULL存储类的值比所有其它值都小(包括其它具有NULL存储类的值)。在NULL值之间,没有特别的可排序值。
- INTEGER或REAL存储类值高于NULL,它们的类值相等。INTEGER值和REAL值通过其数值进行比较。
- TEXT存储类的值比INTEGER和REAL高。数值永远比字符串的值低。当两个TEXT值进行比较时,其值大小由“排序法”决定。
- BLOB存储类具有最高的类值。具有BLOB类的值大于其它所有类的值。BLOB值之间在比较时使用C函数memcmp()。
所以,当SQLite对一个字段进行排序时,首先按存储类排序,然后再进行类内的排序 (NULL类内部各值不必排序) 。
性能优化
1、优化策略一: 插入语句的书写方式
逐行插入的效率远远低于多行插入
开发中,我们尽量多些多行插入,避免出现逐行插入的操作。
2、优化策略二: 插入数据库大小导致内存溢出
从硬盘上不断的读写操作,对大文件持续读写,会增加内存的增加,
这是在插入过程中,数据被锁住(locked)后,会不断生成journal文件,通过这个文件不断写入数据库中,这样不间断的写入读取,就增加了内存消耗。
更多查看:Sqlite3开发你一定要知道的大数据插入优化策略