SQLite
SQLite基础知识
-
SQLite数据库功能特性:ACID事务;支持数据库大小至2TB;足够小,大致13万行C代码4MB左右;存储在单一磁盘文件中的完整数据库。独立,无额外依赖。源码完全开源。支持多种编程语言,如 C/C++、PHP、Java、Python 等。
-
ACID:在 DBMS 写入或更新数据过程中,为保证事务正确可靠,具备原子性、一致性、隔离性、持久性 4 个特性 。
-
常用指令
-
创建SQ Lite数据库及创建表
-
sqlite">sqlite> .databases main: "" r/w sqlite> .open studetndb.db --通过打开方式创建数据库,如果已经存在,直接打开,否则直接创建数据库 sqlite> .databases main: E:\sqlite\studetndb.db r/w sqlite> .tables sqlite> create table tbl(stuno,stuname); sqlite> .tables tbl sqlite> insert into tbl values(101,'dell'); sqlite> .tables tbl sqlite> select *from tbl; 101|dell sqlite> insert into tbl values(102,'dxll'); sqlite> select *from tbl; 101|dell 102|dxll
-
SQLite数据库:附加与分离
附加数据库
sqlite">sqlite> .databases
main: "" r/w
sqlite> attach database 'db1.db' as 'db1test'...> ;
--没有 db1test 就新建
sqlite> .databases
main: "" r/w
db1test: E:\sqlite\db1.db r/w
sqlite> attach database 'db1.db' as 'db1test2';
sqlite> .databases
main: "" r/w
db1test: E:\sqlite\db1.db r/w
db1test2: E:\sqlite\db1.db r/w
分离数据库
detach database 数据库名称
sqlite">sqlite> detach database 'db1test';
sqlite> .databases
main: "" r/w
db1test2: E:\sqlite\db1.db r/w
SQLite数据类型
SQLite存储各类和数据类型
- 数据值:
- NULL:表示该值为NULL值
- INTEGER:整型值
- REAL:浮点值
- TEXT:文本字符串,存储使用的编码方式为UTF-8、UTF-16BE,UTF-16LE。
- BLOB:存储Blob数据,该类型数据和输入数据完全相同
- 日期和时间数据类型:和布尔类型一样,SQLite也同样没有提供专门的日期时间存储类型,而是以TEXY、REAL和INTEGER类型分别表示不同的格式表示该类型。
- TEXT (‘YYYY-MM-DD HH:MM:SS’)
- REAL:从公元前4714年11月24日格林尼治时间的正午计算的天数。
- INTEGER:从1970-01-01 00:00:00 UTC 算起的秒数
- 布尔类型:SQLite没有提供专门的布尔类型,存储为0 1整数
SQLite五种亲缘类型
最大化SQLite和其他数据库引擎之间额数据类型兼容性,SQLite提出类型亲缘性(type affinity)
- TEXT:数值型数据在被插入之前,需要先被转换为文本格式,之后再插入到目标字段中。
- NUMERIC:当文本数据被插入到亲缘性为 NUMERIC 的字段中时,如果转换操作不会导致数据信息丢失以及完全可逆,那么 SQLite 就会将该文本数据转换为 INTEGER 或 REAL 类型的数据,如果转换失败,SQLite 仍会以 TEXT 方式存储该数据。
- INTEGER:对于亲缘类型为 INTEGER 的字段,其规则等同于 NUMERIC,唯一差别是在执行 CAST 表达式时。
- REAL:其规则基本等同于 NUMERIC,唯一的差别是不会将 “30000.0” 这样的文本数据转换为 INTEGER 存储方式。
- NONE:不做任何的转换,直接以该数据所属的数据类型进行存储。
INTEGER(假设类型字符串当中包含 INT,此字段亲缘类型为 INEGER)
- INT、INTEGER(取值范围足够大,不用担心超限问题)
- TINYINT:枚举类型
- SMALLINT:用于小范围的统计数据
- MEDIUMINT:用于比较大整数的计算
- BIGINT:处理巨大整数才用到。
TEXT
- VARCHAR 可变长度的字符串
- TEXT:一个文本字符串
- CLOB:大文本、大字段
REAL
- REAL:浮点值,以 8 个字节指数形式存储
- FLOAT:单精度
- DOUBLE:双精度
NUMERIC
- DECIMAL:小数值
- NUMERIC:精确数字类型
- DATE:日期类型
- DATETIME:日期时间类型
SQLite 比较表达式:=、==、<、<=、>、>=、!=、IN、NOT IN、BETWEEN、IS、IS NOT。
SQLite 操作符: + - * / % << >> & and | 。
创建表&删除表
-
create table 语法:
-
sqlite">create table 鼠标名称( 字段名称1 数据类型1 约束等条件, 字段名称2 数据类型2 约束等条件, 字段名称3 数据类型3 约束等条件, ...)
-
-
SQLite常用约束条件
-
sqlite">NOT NULL 约束:确保某列不能有 NULL 值。 DEFAULT 约束:当某列没有指定值时,为该列提供默认值。 UNIQUE 约束:确保某列中的所有值是不同的。 PRIMARY Key 约束:唯一标识数据库表中的各行 / 记录。 CHECK 约束:CHECK 约束确保某列中的所有值满足一定条件。
-
-
Navicat:
-
sqlite">--------创建数据表 -- 学生表 create table student( sno INT primary key not null, --学号 sname text not null,--姓名 ssex text not null,--性别 sdept text --所在系、学员 ); -- 课程表 create table course( cno int PRIMARY KEY not NULL, --课程编号 cname text not null, --课程名称 ccredit int --课程学分 );--学生选课表 create table sc( sno int PRIMARY KEY NOT NULL, --学号 cno int NOT NULL, --课程编号 score int --考试分数 ); select *FROM sqlite_master; ----------删除数据表 drop table sc;
-
insert into 语句
sqlite">INSERT INTO TABLE_NAME[(cloumn1,cloumn2,cloumn3,...cloumnN)] VALUES (value1,value2,value3...,valueN);
INSERT INTO TABLE_NAME VALUES (value1, value2,value3 ..., valueN) ; --不指定列名按顺序即可
sqlite">--查询输出student数据表
select *from student;--向student数据表插入一条记录
insert into student(sno,sname,ssex,sage,sdept)
values(101,'张华','男',21,'计算机系');
insert into student(sno,sname,ssex,sage,sdept)
values(102,'张ss','女',22,'外语系');--未指定数据表中的字段
insert into student values(103,'刘ss','女',23,'生物系');
select & update & delete
select用法
sqlite">-- 查询student表中所有记录
SELECT * FROM "student"-- 只查询student表中的:学号、姓名
SELECT Sno as '学号', Sname as '姓名' FROM Student-- SQLite 算术运算符
select 10 + 20;
select 10 - 20;
select 10 * 20;
select 10 / 20;
select 10 % 20;--查询表结构信息
PRAGMA table_info(course);-- SQLite比较运算符
SELECT * FROM student WHERE sage = 19;
SELECT * FROM student WHERE sage > 19;-- SQLite 逻辑运算符
SELECT *FROM student WHERE sage >= 19 and sage <= 21
SELECT *FROM student WHERE sname LIKE '张%' --模糊匹配
SELECT *FROM student WHERE sage in(19,21); --19 和 21
SELECT *FROM student WHERE sage not in(19,21); -- 非 19 和 21SELECT *FROM student WHERE sage BETWEEN 20 and 24; -- 非 19 和 21-- SQLite表达式
SELECT *FROM student WHERE ssex='女' and sage = 22;
update & delete
sqlite">-- SQLite UPDATE 语句操作
UPDATE student
SET sage = 32
where sno = 1004 --将学号为1004的年龄改为32-- SQLite delete 删除语句
DELETE FROM student WHERE sno = 1004; --用主键作为条件,防止删除多个
联合查询
sqlite">select student.sno,student.sage,student.ssex,student.sname,student.sdept,sc.cno,sc.score
from student,sc
WHERE(student.sno=sc.sno);
1001 21 男 张华 计算机系 101 98
1003 23 女 刘ss 物理系 105 99
1008 22 女 叶知夏 生物系 106 89
1006 19 男 陈嘉佑 生物系 104 88
distinct & orderby & groupby
-
dinstinct 专用于消除重复记录
-
sqlite">-- 通过distinct关键字,消除重复这个字段 select DISTINCT sname from staff;
-
-
order by 专用于对一个或多个字段按升序或者降序排列数据
-
sqlite">-- ASC | DESC 从小到大(默认) | 从大到小 order by SELECT *FROM staff ORDER BY ssalary ASC; SELECT *FROM staff ORDER BY ssalary DESC;
-
-
group by 子句专用于配合相同数据进行分组
-
sqlite">-- 相同数据进行分组 select sid, sname,sage,sdepartment,spost, ssalary, sum(ssalary) from staff group by sname ORDER by sname;
-
-
having子句专用于指定条件 来过滤将数据,having子句由group by子句创建的分组在设置条件
-
sqlite">-- 过滤数据 select *FROM staff GROUP by sname HAVING COUNT(sname)<2 --姓名只出现一次的 select *FROM staff GROUP by sname HAVING COUNT(sname)=2 --姓名只出现一次的 -- 1 andy 29 开发部 工程师 15000
-
SQLite触发器
SQLite触发器是数据库的一个回调函数,在指定的数据库事件发生时,自动执行或调用。比如insert、update、delete时等触发。
sqlite">select * FROM staff;select * FROM staff_log;--创建staff员工表对应日志表
create table staff_log(
Staff_ID INT NOT NULL,
Staff_Date TEXT NOT NULL
);-- 创建触发器 staff数据表--->监控此表插入记录事件
CREATE TRIGGER staff_logtrigger after INSERT -- 对 staff 执行插入操作后
ON staff
BEGINinsert into staff_log(Staff_ID,Staff_Date) VALUES(new.SID,datetime('now'));
END--- test datainsert into staff values(15,'yuuny',38,'财务部','会计',16000);
-- 15 2025-02-27 06:12:49
insert into staff values(16,'say',32,'财务部','出纳',17000);
16 2025-02-27 06:14:58-- 查询刚创建的触发器:staff_logtrigger
SELECT name from sqlite_master
where type='trigger';-- 删除触发器
DROP TRIGGER staff_logtrigger;
SQLite索引
索引index是一种特殊查找表,数据库搜索引擎用来加速数据检索功能
sqlite">CREATE INDEX 索引名称 ON 数据表名称;
- 搜索码:表示的是记录各种字符段的一个集合,它可以是一个或者多个字符段的任意序列组合,并不是唯一的一个标识记录。
- 数据目录项: 为索引的相关元素,在建立索引的过程中,数据目录项一般具有各种不同的选择方式
- 记录ID:每一个/段索引在存储内容中唯一的一个标识符。
- 单列索引(基于表的一个列上创建索引)
- 唯一索引(唯一索引不允许任何重复的值插入到数据表当中:create unique index)
- 组合索引(基于表的两个或多个列创建索引)
- 隐式索引(在创建数据表的时候,由数据库服务器自动创建索引)
sqlite">--查询数据表:staff
SELECT * FROM staff;-- 创建索引
CREATE INDEX staff_ssalary_index on staff(SSalary);-- 查找索引
SELECT * FROM sqlite_master WHERE type='index'-- 通过索引查询数据
SELECT *FROM staff indexed by staff_ssalary_index WHERE ssalary >= 10000SELECT *FROM staff WHERE ssalary >= 10000
--删除索引
drop index staff_ssalary_index;
优缺点
-
优点
-
避免使用
- 数据表比较小不要使用索引
- 索引不应该出现在频繁操作的列当中
- 索引应该使用在由大量的NULL值列上
- 又频繁大笔批量数据实现更新、增加、删除操作的。
SQLite 视图
视图则为一张虚拟表,它内容数据由查询决定。视图并不在数据
库中存储的数据值形式存储,记录和字段由自由视图的查询所引用的
表,并且在引用视图时动态生成。
视图是存储在数据库中查询 SQL 语句:安全原因、可以使复杂
的查询易于理解和使用。可以在视图上创建一个触发器。
优势:视点集中简化操作定制数据安全性问题。
SQLite 事务
**数据库事务( transaction)**是访问并可能操作各种数据项的
一个数据库操作序列,这些操作要么全部执行,要么全部不执行,
是一个不可分割的工作单位。事务由事务开始与事务结束之间执
行的全部数据库操作组成。
2、事务属性
**原子性(Atomicity):**事务中的全部操作在数据库中是不可
分割的,要么全部完成,要么全部不执行。
**一致性(Consistency):**几个并行执行的事务,其执行结果
必须与按某一顺序串行执行的结果相一致。
**隔离性(Isolation):**事务的执行不受其他事务的干扰,事务
执行的中间结果对其他事务必须是透明的。
**持久性(Durability):**对于任意已提交事务,系统必须保证
3、事务控制命令
- begin transaction:事务处理
- commit:提交事务
- rollback:回滚事务
通过事务方式对数据库进行访问优势:
- 能够保证数据的读一致性;
- 在数据永久改变前,可以预览数据变化;
- 把逻辑相关的操作分成一个组。
sqlite">select * FROM staff
--事务处理
BEGIN;
DELETE FROM staff WHERE sid=2;
--事务提交 提交之后无法回滚
COMMIT;
--事务回滚
ROLLBACK;
Qt操作SQLite数据库实战
1、QSqlDatabase 类
该类专门用于处理和数据库的连接。头文件需要导入
QSqlDatabase
。
在工程 qmake.pro 文件中加入 SQL 数据库支持:
QT +=sql
2、Qsqlquery 类
QSqlQuery
类提供执行和操作 SQL 语句的各种方法。比如执行
DML(数据操作语言)语句,如 select/insert/delete/update 及
DLL(数据定义语言),如 create table/create view 等。
CreateSQLConnection.h
#ifndef CREATESQLCONNECTION_H
#define CREATESQLCONNECTION_H#include <Qtsql/qsqldatabase>
#include <QSqlQuery>
#include <QMessageBox>static bool CreateSQLConnectionFunc()
{QSqlDatabase sqldb=QSqlDatabase::addDatabase("QSQLITE");sqldb.setDatabaseName("test.db");if(!sqldb.open()){QMessageBox::critical(0,"错误","SQLite数据库打开失败,请重新打开",QMessageBox::Ok);return false;}else{QMessageBox::information(0,"正确","SQLite数据库打开成功!",QMessageBox::Ok);}QSqlQuery queryexec;//创建数据表queryexec.exec("create table emp(empid int primary key,empname varchar(20))");//插入记录queryexec.exec("insert into emp values(101,'vico')");queryexec.exec("insert into emp values(102,'abd')");queryexec.exec("insert into emp values(103,'eve')");queryexec.exec("insert into emp values(104,'lot')");queryexec.exec("insert into emp values(105,'clat')");return true;
}
#endif // CREATESQLCONNECTION_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"#include "CreateSQLConnection.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug()<<"正在连接SQLite数据库......";if(!CreateSQLConnectionFunc()){QMessageBox::information(0,"错误","数据库创建失败,请重新检查",QMessageBox::Ok);}QSqlQuery query;query.exec("select *from emp");qDebug()<<"职工编号"<<"职工姓名";while(query.next()){qDebug()<<query.value(0).toInt()<<qPrintable(query.value(1).toString());}
}MainWindow::~MainWindow()
{delete ui;
}