<p><strong><strong>前言</strong></strong></p><p>数据在实际工作中应用非常广泛,数据库的产品也比较多,oracle、DB2、SQL2000、mySQL;基于嵌入式linux的数据库主要有SQLite, Firebird, Berkeley DB, eXtremeDB。</p><p>本文主要讲解数据库SQLite,通过这个开源的小型的嵌入式数据库带领大家掌握一些基本的数据库操作,这些操作在很多系统中都是通用的,可谓学一通百。</p><p><strong><strong>SQLite</strong></strong></p><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-dbc0c7525cfae188.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。</p><p><strong><strong>作者D.RichardHipp</strong></strong></p><p>2000年1月,Hipp开始和一个同事讨论关于创建一个简单的嵌入式SQL数据库的想法,这个数据库将使用GNU
DBM哈希库(gdbm)做后台,同时这个数据库将不需要安装和管理支持。后来,一有空闲时间,Hipp就开始实施这项工作,2000年8月,SQLite
1.0版发布了。【在此向大神献上我的膝盖!】</p><p>它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如
Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。</p><p><strong><strong>SQLite特性</strong></strong></p><ol><li><p>零配置一无需安装和管理配置;</p></li><li><p>储存在单一磁盘文件中的一个完整的数据库;</p></li><li><p>数据库文件可以在不同字节顺序的机器间自由共享;</p></li><li><p>支持数据库大小至2TB;</p></li><li><p>足够小,全部源码大致3万行c代码,250KB;</p></li><li><p>比目前流行的大多数数据库对数据的操作要快。</p></li></ol><p><strong><strong>安装</strong></strong></p><p>现在运行的主要是sqlite3版本,在ubuntu下安装也非常方便。</p><pre>sudo apt-get install sqlite sqlite3 安装应用程序
sudo apt-get install libsqlite3-dev 安装库+头文件,用代码操作数据库必须安装</pre><p>查看版本号: 输入命令 sqlite3进入操作界面,输入命令.version,即可查看详细版本号。</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-5b76265622e87398.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>也可以使用下面命令,安装图形化操作工具:</p><pre>sudo apt-get install sqlitebrowser 图形化工具建立数据库</pre><p>除此之外,还可以部署在windows下,本文只讨论ubtuntu下,采用命令行方式来操作数据库。</p><p><strong><strong>数据类型</strong></strong></p><p>操作数据库,主要就是操作表,表的每一列内容都有一定数据类型,比如整型值、字符串、布尔型等。</p><p><strong>Sqlite3主要数据类型如下:</strong></p><p>ble d<strong>at</strong>a-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"></p><p>同时sqlite3也接受如下的数据类型:</p><p>ble d<strong>at</strong>a-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"></p><p><strong><strong>约束</strong></strong></p><p>表的每一列都有一些限制属性,比如有的列的数据不能重复,有的则限制数据范围等,约束就是用来进一步描述每一列数据属性的。 SQLite 数据库常用约束如下:</p><p>ble<strong> d</strong>ata-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"></p><p><strong><strong>非空 NOT NULL</strong></strong></p><p>有一些字段我们可能一时不知到该填些什么,同时它也没设定默认值,
当添加数据时,我们把这样的字段空着不填,系统认为他是 NULL 值。但是还有另外一类字段,必须被填上数据,如果不填,系统就会报错。
这样的字段被称为 NOT NULL 非空字段,需要在定义表的时候事先声明。</p><p><strong><strong>唯一 UNIQUE</strong></strong></p><p>除了主列以为,还有一些列也不能有重复值。</p><p><strong><strong>主键 PRIMARY KEY</strong></strong></p><p>一般是整数或者字符串,只要保证唯一就行。 在 SQLite 中,主键如果是整数类型,该列的值可以自动增长。</p><p><strong><strong>外键 FOREIGN KEY</strong></strong></p><p>我们的数据库中已经有
Teachers 表了,假如我们再建立一个 Students 表, 要求 Students 表中的每一个学生都对应一个 Teachers
表中的教师。 很简单,只需要在 Students 表中建立一个 TeacherId 字段,保存对应教师的 Id 号,
这样,学生和教师之间就建立了关系。 问题是:我们有可能给学生存入一个不在 Teachers 表中的 TeacherId 值,
而且发现不了这个错误。 这种情况下,可以把 Students 表中 TeacherId 字段声明为一个外键, 让它的值对应到 Teachers
表中的 Id 字段上。 这样,一旦在 Students 表中存入一个不存在的教师 Id ,系统就会报错。</p><p><strong><strong>默认值 DEFAULT</strong></strong></p><p>有一些特别的字段列,在每一条记录中,他的值基本上都是一样的。只是在个别情况下才改为别的值,这样的字段列我们可以给他设一个默认值。</p><p><strong><strong>条件检查 CHECK</strong></strong></p><p>某些值必须符合一定的条件才允许存入,这是就需要用到这个 CHECK 约束。</p><p><strong><strong>常用命令</strong></strong></p><p>下面介绍Shell模式中的各常用命令的使用。</p><p>ble<strong> d</strong>ata-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal"></p><p>【注意】sqlite的命令都是.开头的,操作语句前面是没有.的。</p><p><strong><strong>使用实例</strong></strong></p><p>数据库的操作语句主要是增删改查,下面我们通过一些实例让大家了解数据库的这些基本操作。</p><p><strong><strong>表类型</strong></strong></p><p>假设我们要创建一个教学管理的数据库jxgl.db,数据库中要保存学生表STUDENT。</p><p>ble <strong>data-</strong>d<strong>raft</strong>-<strong>node</strong>=<strong>"bloc</strong>k" data-draft-type="table" data-size="normal" data-row-style="normal"></p><p>根据我们的常识,可知每一列的数据有以下特性:</p><ul><li><p>sno 学号:整型值,每个人学号是唯一的,学校一般用学号来区分所有的学生,而且一般学号是递增的,所以我们设置sno为primary key;</p></li><li><p>sname 姓名:一般是字符串,可以重复,但是不能为空;</p></li><li><p>ssex 性别:字符串,可以为空;</p></li><li><p>sage 年龄:整型值,假定年龄要大于14;</p></li><li><p>sdept 专业:字符串,可以为空,此处我们默认为'CS'。</p></li></ul><p>下面我们一步步实现这个数据库的所有操作。</p><p><strong><strong>创建教学管理“jxgl”数据库</strong></strong></p><p>数据库的打开和退出,使用如下命令。</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-38cd11a9d6e97280.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>
</p><p><strong><strong>创建表:</strong></strong></p><pre>CREATE TABLE IF NOT EXISTS STUDENT(Sno integer primary key, Sname text not null, Ssex text,Sage integer check(Sage>14),Sdept text default 'CS');</pre><p>该表的属性就是按照上一节表属性 执行结果:</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-c3c0ed8784fcc581.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>
</p><p><strong><strong>查看表:</strong></strong></p><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-84bb2c0c3b99875e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>看到STUDENT,说明该表创建好了。 【注意】</p><ol><li><p>操作语句不是命令,前面不要加. ;</p></li><li><p>操作语句后面一定要;结尾,如果漏掉了,一定要补上分号;</p></li><li><p>操作语句对字母的全角半角很敏感,所有的符号都要用半角。</p></li></ol><p><strong><strong>插入数据</strong></strong></p><p>插入数据采用insert into语句来实现,如下所示:</p><pre>INSERT INTO STUDENT VALUES('95001','李勇','M',20,'CS');
INSERT INTO STUDENT VALUES('95002','刘晨','F',19,'IS');
INSERT INTO STUDENT VALUES('95003','王敏','F',18,'MA');
INSERT INTO STUDENT VALUES('95004','张立','M',18,'IS');</pre><p>执行结果如下:</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-25aeacd50b14c74e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>插入的数据只初始化部分值</strong></strong></p><p>设置了not null那一列 必须要赋值,而且表名字不区分大小写。</p><pre>insert into student(sname,sage) values ('一口',19);</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-63abca97f378156e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>查看表</strong></strong></p><p>用SELECT语句查看表中的内容:</p><pre>SELECT FROM STUDENT;</pre><p>其中的 * 表示查看所有的数据信息。</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-b4625506bcf2faa1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>有没有看到,结果看起来不舒服啊,下面我们来调整下显示格式:</p><pre>sqlite> .headers on 显示列名
sqlite> .mode column 列对齐</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-a3284a8f12977ba4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>删除一行信息</strong></strong></p><pre>delete from student where sname='一口';</pre><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-1a2fadd6483b0de3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>由上图可见,名字为“一口”的那条记录被删除了。</p><p><strong><strong>修改一条记录的某个内容</strong></strong></p><pre>UPDATE student SET sage=29 WHERE sname='张立';</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-0f80cf02282b9a64.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>修改数据表结构。</strong></strong></p><p>修改表结构,需要用到语句ALTER TABLE。 下面我们向STUDENT表增加“spwd”列,其数据类型为TEXT型,用SELECT命令查看表中内容。</p><pre>ALTER TABLE STUDENT ADD spwd TEXT default '123456';</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-e1f5c71ea118bf3c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>修改表名字</strong></strong></p><pre>alter table student rename to stu;</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-f40fa302ea13127c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>删除数据表。</strong></strong></p><pre>DROP TABLE STUDENT;</pre><p><strong><strong>删除列</strong></strong></p><p>sqlite3没有实现删除一列的命令,要实现这个操作,需要先将该表拷贝到一个新表,但是只集成需要的列,要删除的列不继承过来。 可以 用以下方式操作删除一列:</p><pre>sqlite> create table test as select sno, sname,ssex,sage,sdept from stu;
sqlite> drop table stu;
sqlite> alter table test rename to stu;</pre><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-d6d152bdfbb3a850.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>由上图可知,我们刚才增加的列spwd被删除了。</p><p><strong><strong>sqlite进阶</strong></strong></p><p><strong><strong>where子句</strong></strong></p><p>如果我不想查看所有的数据,而指向查看某一个人的信息要怎么操作呢? 我们就要借助where子句来实现。 where子句可以结合操作语句来进程增删改查,是最常用的一个子句。</p><p><strong>根据姓名查找记录:</strong></p><pre>Select from student where sname='一口';</pre><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-36984f460a69be0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong>根据学号查找记录:</strong></p><pre>Select from student where sno=95001;</pre><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-36da245acc748f08.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong>根据姓名和年龄同时查找记录:</strong></p><pre>select from student where sname='一口' and sage=19;</pre><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-ece728ad9dee12dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong>显示某两列的数据</strong></p><pre>select sno,sname from student ;</pre><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/23850874-f8adcf4d8e58c82f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p><strong><strong>数据库的备份和恢复</strong></strong></p><p>现在我们假设要将表foods备份出为foodsdb.sql,并用命令回复该数据库。 按照以下步骤操作即可。</p><pre>sqlite>.dump --把创建表及向表中插入记录的所有SQL语句显示在屏幕上
sqlite>.output foodsdb.sql --指定dump命令输出到文件的文件名
sqlite>.dump --输出创建并插入数据到基本表的SQL语句到output指定的文件
sqlite>.output stdout --恢复输出内容到标准输出设备(屏幕)
sqlite>.dump --此时输出的SQL语句转回到屏幕
sqlite>Drop table foods; --删除foods表语句说明:</pre><p>上述Drop为SQL语句,用于删除指定的表。因为是SQL语句,因此以“;”结尾</p><pre>sqlite>.read foodsdb.sql --执行foodsdb.sql中的包含的所有SQL语句,用来重建刚删除的4张表及相关数据</pre><p>好了,跟着一口君一步步操作,基本上sqlite3的增删改查操作,相信各位应该没什么问题了,sqlite还有其他一些子句以及函数的用法,留待下一篇继续介绍。</p><p>获取更多关于Linux的资料,请关注公众号「一口Linux」</p><p>
</p>