sqlite数据库
sqlite数据库是嵌入式最常用的,sqlite是一种轻量级的关系型数据库,本体只有几兆大小。
安装
通过apt命令进行sqlite数据库的安装
sudo apt install sqlite
sqlite3 表示安装成功
.exit ,或者 .quit 进行退出
常见的数据类型
常见函数
函数名 | 解释 |
---|---|
count | 统计数据总行数 count(*) |
avg | 统计指定列的平均值 avg(score) |
min | 指定列的最小值 min(age) |
max | 指定列的最大值max(age) |
sum | 对指定列求和sum(score) |
数字类型
- 长整型:int(-2147483648~2147483647)
- 短整型:smallint(-32768~32767)
- 微整形:tinyint(-128~127)
- 单精度:float
- 双精度:real
字符串类型
- 定长非unicode :char 字符串类型
- 变长非unicode: varchar 字符串类型
- 变长长非unicode : text 字符串类型
- 定长:无论存储的数据长度如何,都会占用相同的存储空间
- 变长:它只占有必要的存储空间加上一个额外的字节用于记录字符串的长度
- 定长unicode:字符串类型 nchar
- 变长unicode : nvarchar 字符串类型
- 变长长unicode: ntext 字符串类型
- unicode字符数据:每个字符串占用两个字节,能够有效地存储各种语言字符
sql语句约束条件
- 判断表不存在:
if not exists
- 希望某个字段不重复:
unique
- 不可为空:
not null
- 主键(唯一、不可为空):
primary key
- 默认:
default
- 自动增长:
AUTOINCREMENT
数据库相关操作
.open 文件名
如果文件名存在,就只做打开操作,如果文件名不存在,新建并打开.tables
查看当前数据库中所有的表.schema
表名: 查看指定表的表结构
数据库表相关语句DDL
创建表create
c
creat table 表明(
字段(列)1 数据类型 约束条件,
字段(列)2 数据类型 约束条件,
......
);
-----------------------------------
create table hero(
id int primary key,//主键,id必须指定值,而且不能重复
name text,
attack float,
job text
);
//只有当指定表明不存在的时候才创建表格
create table if not exists hero(
id int primary key,
name text,
attack float,
job text
);
删除表drop
c
drop table 表名;
比如:删除hero表
drop table hero;
新增字段add
c
alter table 表名 add 字段名 数据类型 约束条件;
---------------------------------------------
alter table hero add location text;//给hero表格添加一列location字段,字段类型text
也可以在添加字段的时候给字段设置约束条件,比如添加level字段,并要求level字段不能为空,并将默认值设置为1
c
alter table hero add level int not null default 1;
删除字段
其他数据库删除字段
c
alter table 表名 drop column 字段名;
sqlite
中删除字段
新建一个表格,将原来表格要删除的字段,其余的字段都加入其中,比如要删除hero表中的attack字段和job字段,那么就新建一个表格hero_data,将剩余的字段加入其中。
create table hero_data( id int; name text; );
将旧表中对应的数据查询出来,并放到新表对应字段中
insert into hero_data (id,name) select id,name from hero;
修改表名rename to
c
alter table 旧表名 rename to 新表名
-----------------------------------------
alter table hero rename to hero_data;
数据库表语句 DML
插入数据 insert
c
insert into 表名 values(数据1,数据2......);
创建语句
c
create table if not exists hero(
id int primary key,
name text,
attack float,
job text
);
------------------------------------------------
insert into hero values(1,"鲁班",100,"射手");
//查询hero中所有字段值
select * from hero;
//插入多条用逗号隔开
insert into hero values(2,"芈月",50,"法师"),(3,"典韦",120,"疯狗"),(4,"瑶",20,"混子");
//插入指定字段的数据
insert into 表名 (字段1,字段2,...) values(字段1值,字段2值,...);
--------------------------------------------------------------
insert into hero (name,job) values("甄姬","法师");
insert into hero (job,name) values("法师","安琪拉"),("辅助","牛魔");//插入多条
查询语句如果需要显示标题,查询之前,设置如下命令:
- 打开字段名显示:
.headers on
- 关闭字段名显示:
.headers off
- 格式化:
.mode column
- 回复默认:
.mode list
mode有很多种用法
查询语句select
c
select * from 表名;//查询所有数据
select 字段1,字段2,... from 表名;//查询某些字段数据
select 字段1 别名 , 字段2 别名 from 表名;//查询某些字段数据并取别名
select * from 表名 where 条件;//条件查询
select * from COMPANY where AGE<25; //查询当前表中所有小于25岁的
select * from hero where job="法师" and attack=50; //并列查询
select * from hero where job='法师' or job='疯狗';//选择查询
删除数据delete
c
delete from 表名 where 条件;
delete from hero where job='混子';
注意: 删除数据时,一定要给条件,如果不给条件,删除的是全部数据
修改数据update
c
update 表名 set 字段1=值1,字段2=值2,... where 条件;
update COMPANY set AGE=25 where ID=1;//将id为1的年龄修改为25
update COMPANY set AGE=35,SALARY=40000 where ID=2; //多条修改逗号隔开
注意: 如果修改数据时,不给条件,那么最终会将该字段全部数据都做修改
内联复杂语句DQL
分组查询group by
分组查询是以组为条件,对查询的结果分组显示,采用group by子句进行分组
count(*)
分组函数,作用就是分组之后,统计每个组的数据条数
c
select count(*),sex from emp group by sex;//查询男性员工和女性员工分别有多少人
select count(*) num,sex from emp group by sex;//起别名
having关键字
分组之后,对分组字段进行筛选,这个时候,不能使用where而应该使用having
c
select count(*) num,sex from emp group by sex having count(*)>3;
或者
select count(*) num,sex from emp group by sex having num>3;
查询排序
在sql语句的编写过程中,对于排序的要求也十分常见,一般排序是指对一些列按照从高到低或者从低到高显示。
order by 字段 asc:升序排序
order by 字段 desc:降序排序
c
//显示所有员工信息,按照薪资从低到高排序
select * from emp order by sal asc;
分页查询
sqlite数据中如果需要对结果集限制其显示的条数,可以通过limit关键字实现,limit关键字后面通常会跟1-2个参数,表示如下:
limit n:表示限制结果显示n条
limit m,n:表示从第m(不含)条开始,显示n条数据
c
//查询员工表中收入最高的前三条数据
select * from emp order by sal desc limit 3;
select * from emp order by sal desc limit 0,3;
//查询员工工资排名在4-6之间的员工
select * from emp order by sal desc limit 3,3;
//条目数从0开始
//查询员工工资排名在7-9之间的员工
select * from emp order by sal desc limit 6,3;
模糊查询like
c
查询姓悟的员工
select * from emp where ename like "悟%";
查询员工名字以娥结尾的员工
select * from emp where ename like "%娥";
查询员工名字包含"空"的员工
select * from emp where ename like "%空%";
多表查询
对于数据系统来说,常规的查询操作大多数时候都会涉及到多张表数据,因此多表联合查询中需要重点掌握。
所谓的连接查询即将多个使用公共字段连在一起,常见的连接查询包含:
1.等值查询(内连接)
2.左连接(左外连接)
3.部分数据库还有(右连接,全外连接)
c
select * from emp,department where emp.dno=department.dno;//emp.dno跟depart.dno 一致相同
等值连接(内连接)
c
//查询员工的姓名,职位,月薪,部门号,部门名称
select ename,job,sal,emp.dno,dname from emp,department where emp.dno=department.dno;
//关联查询的时候,使用字段时,最好标注来自于那个表,
//避免当两个表有重复字段时出错
select e.ename,e.job,e.sal,e.dno,d.dname from emp e,department d where e.dno=d.dno;
//内连接写法
//from 表1 inner join 表2 on 连接条件
select e.ename from emp e inner join department d on e.dno=d.dno;
左连接left join
左连接是以left join左边的表作为驱动表,以右边的表作为匹配表,会显示左侧表中的所有的数据。
c
//查询员工的姓名,职位,月薪,部门号,部门名称
//以emp作为驱动表
select e.ename,e.job,e.sal,e.dno,d.dname from emp e left join department d on e.dno=d.dno;
//以department作为驱动表
select e.ename,e.job,e.sal,e.dno,d.dname from department d left join emp e on e.dno=d.dno;
子查询
多表联合查询的时候,出来可以使用连接查询以外,也可以使用子查询,子查询根据场景分为:当行单列子查询、当列多行子查询、多行多列子查询
所谓的子查询,就是将一个查询的结果当作另外一个查询的条件。
1.单行单列子查询:子查询出来的结果只有一行一列
c
//查询出销售部所有员工的信息
1.查询出销售部门的部门号
select dno from department where dname='销售部';
//查询出来的结果为2
2.拿着dno=2去emp表中查询 部门号为2的员工
select * from emp where dno=2;
将1,2合并
select * from emp where dno=(select dno from department where dname='销售部');
此种情况,括号中的查询语句,就称为子查询,虽然使用子查询能够解决复杂的查询要求,但是时间复杂度较高,因此不推荐以上的查询,使用连接查询能够更高效的解决。
单列多行子查询:子查询的结果是一列多行
c
查询出销售部和研发部的所有员工
1.查询出销售部和研发部的部门号
select dno from department where dname='销售部' or dname='研发部';
查询出1和2
2.根据部门号查询员工信息
select * from emp where dno=1 or dno=2;
字段in(值1,值2...)字段的值是否满足括号in中的任意一个值
select * from emp where dno in (1,2);
3.连接
select * from emp where dno in (select dno from department where dname='销售部' or dname='研发部');
select * from emp where dno in (select dno from department where dname in ('销售部','研发部'));
多行多列子查询:子查询出来的结果是多行多列的
c
//查询出所有职位和性别跟悟空一样的员工
1.查悟空的职业和性别
select job,sex from emp where ename='悟空';
//可以将查询出来的结果看成一个表
select e.* from emp e,(select job,sex from emp where ename='悟空') temp where e.job=temp.job and e.sex=temp.sex;
SQLite的索引
索引概述
关于数据库查询优化的方案:
1.尽量使用连接查询代替子查询
2.避免在大数据表中使用like
3.尽量对查询结果限制条数,limit
上述提到的优化方案都是从sql语句层面的查询优化,除了从sql语句层面对查询优化之外,还有很多其他的优化方式:使用索引。
索引(index)是一种特殊的查找表,数据库索引用来加快数据检索。简单的说,索引是一个指向表中数据的指针。一个数据库中的索引与一般书的索引目录是非常相似的。
索引有助于加快select查询和where子句,但是它会减慢使用update和insert语句时的数据输入
创建索引
创建索引的格式:
c
create index 索引名 on 表名;
单列索引:单列索引是一个只基于表的一个列上创建的索引,基本语法:
c
create index 索引名 on 表名(列名);
唯一索引:使用唯一索引不仅仅是为了性能,同时也为了数据的完整性。唯一索引不允许任何重复的值插入到表中,基本语法:
c
create unique index 索引名 on 表名(列名);
组合索引:基于一个表达两个或者多个列上创建的索引,基本语法:
c
create index 索引名 on 表名(列名1,列名2,...);
是否要创建一个单列索引还是组合索引,要考虑到你在查询过滤条件的where子句中使用频繁的列。
如果只是用一个列,就选择单行索引,
where子句中有两个或者多个列经常使用,就选择组合索引
隐式索引:在创建对象时,有数据库服务器自动创建的索引,索引自动创建为主键约束和唯一约束。
在emp表的salary列上创建一个索引
c
create index salary_index on emp(sal);
这样创建索引之后,当执行基于sal列查询的时候,sqlite就会使用索引来加快查询速度。
c
select * from emp where sal=4200;
在sal上面有一个索引,sqlite将会使用这个索引定位到含有4200的行,而不是扫描表中的所有记录。
可以通过.indices 表名或者.indexes 表名查看表中有哪些索引。
c
.indices emp
也可以查看当前数据库中所有的索引
c
select * from sqlite_master where type='index';
删除索引
一个索引可以使用drop命令删除,当删除索引时,应特别注意,因为性能可能会下降
c
drop index 索引名;
需要注意的事项
什么情况下避免使用索引?
虽然索引的目的在于提高数据库的性能,但是这几个情况要避免使用索引:
1.索引不应该使用在较小的表上:可能全表扫描会比索引更快,在这种情况下使用索引可能会引入额外的开销,并且不会带来任何明显的性能优势。
2.索引不应该使用在有频繁的大批量的更新或者插入操作上:使用索引有可能倒置数据不稳定,索引需要在每次数据修改时进行更新,这可能倒置额外的开销和性能的下降。这种情况下,可以考虑只在关键查询的列上添加索引,而在频繁修改的列上避免使用索引。
3.数据表的频率非常低,有些数据表很少被查询,或者只被查询一次。在这种情况下,索引可能不会带来任何明显的优势,因为索引需要占用额外的空间,并且需要在查询时进行额外的运算。如果数据很少被查询,使用索引可能会浪费资源。
4.索引不应该使用在含有大量NULL值的列上。