SQLite------数据库介绍
- [1. SQLite数据库介绍](#1. SQLite数据库介绍)
- [2. QSqlDatabase类介绍](#2. QSqlDatabase类介绍)
-
- [2.1 数据库连接和关闭](#2.1 数据库连接和关闭)
- [2.2 创建表](#2.2 创建表)
- [2.3 插入数据](#2.3 插入数据)
- [2.4 查询数据](#2.4 查询数据)
- [2.5 修改数据](#2.5 修改数据)
- [2.6 删除数据](#2.6 删除数据)
1. SQLite数据库介绍
我们常见熟悉的数据库管理系统有:Oracle,SQLServer,MySQL等,这些数据库管理系统都有一个共同的特点,就是必须先要在本地安装数据库管理系统软件,然后才能使用这些数据库管理系统提供的服务。而这些数据库管理系统的安装和卸载有时候确实最让人头痛的,但是现在有了AI工具的辅助这些都不是什么问题。
而今天我们要介绍一款轻量级,无需安装的桌面型数据库SQLite,SQLite是非常流行的开源嵌入式数据库,将源文件添加到工程里面就可以直接使用。他很好的支持关系型数据库所具备的一些基本功能特点,比如:标准的SQL语法,事务,数据表和索引等。
他的特点主要是。
- 管理简单,甚至可以说不需要管理
- 操作简单,SQLite生成的数据文件可以在各个平台无缝连接
- 可以非常方便的以多种形式嵌入其他应用程序,如静态库,动态库等。
- 易于维护
Qt中已经内置了SQLite,在安装qt开发环境时,SQLite就已经配置好了,只需要在.pro文件中导入数据库模块即可使用
QT += sql
2. QSqlDatabase类介绍
QSqlDatabase类主要处理与数据库的链接,他提供了创建,配置,打开和关闭数据库连接的方法。QSqlDatabase类提供了通过连接访问数据库的接口。QSqlDatabase的一个实例表示该连接。该连接通过一个受支持的数据库驱动程序提供对数据库的访问,该数据库驱动程序派生自QSqlDriver。或者,可以从QSqlDriver中创建自己的数据库驱动程序的子类。
Qt中通过调用静态addDatabase()函数创建一个连接(即QSqlDatabase的一个实例),其中指定要使用的驱动程序或驱动程序类型type(取决于数据库的类型)以及连接名称。连接通过其自身的名称来识别,而不是通过它所连接的数据库的名称来识别。一个数据库可以有多个连接。QSqlDatabase还支持默认连接的概念,即未命名连接。要创建默认连接,在调用addDatabase()时不要传递连接名称参数。随后,如果在没有指定连接名的情况下调用任何静态成员函数,将采用默认连接。
所支持的type类型有:
| 类型名称 | 对应数据库 |
|---|---|
| QDB2 | IBM DB2 (version 7.1 and above) |
| QIBASE | Borland InterBase |
| QMYSQL | MySQL (version 5.0 and above) |
| QOCI | Oracle Call Interface Driver |
| QODBC | Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases |
| QPSQL | PostgreSQL (versions 7.3 and above) |
| QSQLITE2 | SQLite version 2 Note: obsolete since Qt 5.14 |
| QSQLITE | SQLite version 3 |
| QTDS | Sybase Adaptive Server Note: obsolete since Qt 4.7 |
2.1 数据库连接和关闭
C
QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))
本章节我们使用的是SQLite
- 添加SQLite数据库驱动,返回⼀个连接
C
QSqlDatabase texDB = QSqlDatabase::addDatabase("QSQLITE");
- 功能:设置数据库文件的名称 name: 要连接的数据库的名称。对于SQLite,通常是数据库文件的路径;对于其他数据库系统,比如MySQL通常是数据库管理系统中数据库的名称。注意要使其生效,必须在打开连接之前设置数据库名称。或者,可以关闭连接,设置数据库名称,然后再次调用open()。
c
void QSqlDatabase::setDatabaseName(const QString &name)
- 功能:打开数据库连接,即和数据库真正建立连接。返回值:连接成功连接返回true,否则返回false,注意:可以使用isopen()方法检测是否打开 。user:数据库用户名 。password: 数据库密码
c
bool open();
bool open(const QString &user, const QString &password);
- 功能:关闭数据库连接,释放所有资源,并使与数据库⼀起使用的所有QSqlQuery对象无效
c
void close();
案例,实现两个按钮一个按钮实现创建数据库,一个按钮关闭数据库
c
void Widget::on_createDB_clicked()
{
// 加载数据库驱动
textDB = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库名字
textDB.setDatabaseName("textDB.db");
//打开数据库
if (!textDB.open()){
qDebug() << "打开数据库失败:" << textDB.lastError().text();
return;
}
qDebug() << "连接数据库:" <<textDB.databaseName() << " 成功";
}
void Widget::on_close_clicked()
{
// 关闭数据库
qDebug() << "关闭数据库:" <<textDB.databaseName() << " 成功";
textDB.close();
}
创建成功后可以在Debug文件中看到我们创建的数据文件

2.2 创建表
这里创建表的语法和我们之前学习过的MySQL是一样的,这里就不多进行讲解了,如果有不明白的可以去我们专栏链接: MySQL初级进行学习。
SQLite支持的所有类型可以在菜鸟编程中查看详细的介绍,这里只介绍SQLite中的部分。
| 数据类型 | 描述 |
|---|---|
| NULL | 值是一个 NULL 值。 |
| INTEGER | 值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。 |
| REAL | 值是一个浮点值,存储为 8 字节的 IEEE 浮点数字。 |
| TEXT | 值是一个文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储。 |
| BLOB | 值是一个 blob 数据,完全根据它的输入存储。 |
| SQLite | 的存储类稍微比数据类型更普遍。INTEGER 存储类,例如,包含 6 种不同的不同长度的整数数据类型。 |
QSqlQuery 封装了在QSqlDatabase上执行的SQL查询,创建、导航和检索数据所涉及的功能。它可以用于执行DML(数据操作语言)语句,如SELECT、INSERT、UPDATE和DELETE,以及DDL(数据定义语言)语句,如CREATE TABLE。它还可以用于执行非标准SQL的特定于数据库的命令(例如,为PostgreSQL设置DATESTYLE=ISO)。
成功执行的SQL语句将查询的状态设置为active,以便isActive()返回true。否则,查询的状态被设置为非活动。在任一情况下,当执行新的SQL语句时,查询被定位在无效记录上。在检索值之前,必须将活动查询导航到有效记录(以便isValid()返回true)。
- 使用SQL查询和数据库db构造一个QSqlQuery对象。如果未指定db,或者db无效,则使用应用程序的默认数据库。如果查询不是空字符串,它将被执行。
c
QSqlQuery::QSqlQuery(const QString &query = QString(), QSqlDatabase db = QSqlDatabase())
- 数据库表创建好之后,通过QSqlQuery类来执行SQL语句和操作数据库。QSqlQuery类中的exec()函数用来执行SQL语句:
c
// 功能:执⾏SQL语句
// query: 要执行的sql语句,以字符串方式提供
// 返回值:执行成功返回true,否则返回false
bool exec(const QString &query);
// 功能:执⾏SQL语句
// 该⽅法需要提前将SQL语句通过prepare⽅法准备好,然后使⽤bindValue⽅法绑定参数值,
// 最后调⽤exec⽅法执执行
bool exec();
本次案例我们仅仅创建一个学生表。
sql
CREATE TABLE IF NOT EXISTS student(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age REAL,
height REAL
);
示例:实现一个按钮
c
void Widget::on_create_clicked()
{
// 创建sql语句字符串
QString sql("CREATE TABLE IF NOT EXISTS student( \
id INTEGER PRIMARY KEY AUTOINCREMENT,\
name TEXT NOT NULL,\
age REAL,\
height REAL\
)"); // 注意这里sql语句是不需要结尾的分号的
// 创建QSqlQuery对象执行sql语句
QSqlQuery query;
if (!query.exec(sql)){
qDebug() << "创建学生表失败:" << query.lastError().text();
return;
}
qDebug() << "创建学生表成功";
}
SQLite在线查看工具打开网页,直接将生成的textDB.db拖拽到页面,就能看到创建的student表

2.3 插入数据
- 准备要执行的SQL查询。如果查询准备成功,则返回true否则返回false。查询可能包含绑定值的占位符。Oracle样式的冒号-名称(例如:姓氏)和ODBC样式(?)占位符受支持;但是它们不能在同一个查询中混合使用。可移植性注意事项:一些数据库选择延迟准备查询,直到第一次执行查询。在这种情况下,准备语法错误的查询会成功,但是每个连续的exec()都会失败。当数据库不直接支持命名占位符时,占位符只能包含a-zA-Z0-9_范围内的字符。对于SQLite,查询字符串一次只能包含一条语句。如果给出了一个以上的语句,该函数将返回false。
c
//准备SQL语句,该语句中包含⼀个或者多个参数占位符。这些参数占位符在SQL中默认为?表⽰ 也可以⾃定义占位符。其允许提前先设置好SQL语句结构,但是不执⾏
bool QSqlQuery::prepare(const QString &query)
- 在准备好的语句中将占位符placeholder设置为绑定到value。请注意,在指定占位符名称时,必须包括占位符标记(例如:)。如果paramType是QSql::Out或QSql::InOut,则在exec()调用后,占位符将被数据库中的数据覆盖。在这种情况下,必须预先分配足够的空间来存储结果。
c
void QSqlQuery::bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In)
- 将位置pos中的占位符设置为绑定到预准备语句中的值val。字段编号从0开始。如果paramType是QSql::Out或QSql::InOut,则在exec()调用后,占位符将被数据库中的数据覆盖。
c
void QSqlQuery::bindValue(int pos, const QVariant &val, QSql::ParamType paramType = QSql::In)
- 使用位置值绑定时,将值val添加到值列表中,按照建表时成员的顺序绑定。addBindValue()调用的顺序决定了值将在准备好的查询中绑定到哪个占位符。如果paramType是QSql::Out或QSql::InOut,则在exec()调用后,占位符将被数据库中的数据覆盖。
c
void QSqlQuery::addBindValue(const QVariant &val, QSql::ParamType paramType = QSql::In)
示例:通过控制一个按钮和四个QLineEdit进行数据添加,分别对应着添加姓名,年龄,身高和插入模式。

c
void Widget::on_insert_clicked()
{
QSqlQuery query;
if (ui->addModel->text().toInt() == 1){
// 通过命名绑定
query.prepare("INSERT INTO student(name, age, height) VALUES(\
:name, :age, :height)");
query.bindValue(":name", ui->addName->text());
query.bindValue(":age", ui->addAge->text().toDouble());
query.bindValue(":height", ui->addHeight->text().toDouble());
if (!query.exec()){
qDebug() << "通过命名绑定插入表数据失败" << query.lastError().text();
return;
}
qDebug() << "通过命名绑定插入数据成功";
}else if (ui->addModel->text().toInt() == 2){
// 通过位置绑定
query.prepare("INSERT INTO student(name, age, height) VALUES(?, ?, ?)");
query.bindValue(0, ui->addName->text());
query.bindValue(1, ui->addAge->text().toDouble());
query.bindValue(2, ui->addHeight->text().toDouble());
if (!query.exec()){
qDebug() << "通过位置绑定插入表数据失败" << query.lastError().text();
return;
}
qDebug() << "通过位置绑定插入数据成功";
}else if (ui->addModel->text().toInt() == 3){
// 通过表顺序插入数据
query.prepare("INSERT INTO student(name, age, height) VALUES(?, ?, ?)");
query.addBindValue(ui->addName->text());
query.addBindValue(ui->addAge->text().toDouble());
query.addBindValue(ui->addHeight->text().toDouble());
if (!query.exec()){
qDebug() << "通过表顺序插入数据插入表数据失败" << query.lastError().text();
return;
}
qDebug() << "通过表顺序插入数据插入数据成功";
}
}
2.4 查询数据
- 检索结果中的下一条记录(如果有),并将查询定位在检索到的记录上。请注意,结果必须处于活动状态,isSelect()必须在调用此函数之前返回true,否则它将什么也不做并返回false。
以下规则适用:
- 如果结果当前位于第一条记录之前,例如在执行查询之后,立即尝试检索第一条记录。
- 如果结果当前位于最后一条记录之后,则没有变化,并返回false。
- 如果结果位于中间,则尝试检索下一条记录。
- 如果无法检索到该记录,则结果位于最后一条记录之后,并返回false。如果成功检索到记录,则返回true。\
c
bool QSqlQuery::next()
- 返回当前记录中字段索引的值。使用SELECT语句的文本从左到右对字段进行编号,例如字段0是名字,字段1是姓氏。不建议使用SELECT *,因为查询中的字段顺序未定义。如果字段索引不存在,如果查询处于非活动状态,或者如果查询位于无效记录上,则返回无效的QVariant。
c
QVariant QSqlQuery::value(int index) const
- 这是一个重载函数。返回当前记录中名为name的字段的值。如果字段名不存在,则返回无效变量。此重载的效率低于value()
c
QVariant QSqlQuery::value(const QString &name) const
示例:
c
void Widget::on_select_clicked()
{
QString sql("SELECT name, age, height FROM student");
QSqlQuery query;
if (!query.exec(sql)){
qDebug() << "查询数据失败" << query.lastError().text();
return;
}
// 按照字段进行查询
while(query.next()){
qDebug() << query.value("name") << " "
<< query.value("age") << " "
<< query.value("height");
}
qDebug() <<"-------------------";
//按照索引查找
sql = "SELECT name, age, height FROM student";
if (!query.exec(sql)){
qDebug() << "查询数据失败" << query.lastError().text();
return;
}
while(query.next()){
qDebug() << query.value(0) << " "
<< query.value(1) << " "
<< query.value(2);
}
}
2.5 修改数据
c
void Widget::on_updata_clicked()
{
QSqlQuery query;
query.prepare("UPDATE student SET age = :age, height = :height WHERE name = :name");
query.bindValue(":age", ui->updateAge->text().toDouble());
query.bindValue(":name", ui->updateName->text());
query.bindValue(":height", ui->updateHeight->text().toDouble());
if (!query.exec()){
qDebug() << "update数据失败" << query.lastError().text();
return;
}
query.clear();
query.prepare("SELECT * FROM student WHERE name = :name");
query.bindValue(":name", ui->updateName->text());
if (!query.exec()){
qDebug() << "查询数据失败" << query.lastError().text();
return;
}
while (query.next()){
qDebug() << query.value(0) << " "
<<query.value(1) << " "
<<query.value(2) << " "
<<query.value(3);
}
}
2.6 删除数据
c
void Widget::on_delete_2_clicked()
{
QSqlQuery query;
query.prepare("DELETE FROM student WHERE name = :name");
query.bindValue(":name", ui->deleteName->text());
if (!query.exec()){
qDebug() << "delete数据失败" << query.lastError().text();
return;
}
query.clear();
QString sql("SELECT * FROM student");
if (!query.exec(sql)){
qDebug() << "查询数据失败" << query.lastError().text();
return;
}
while (query.next()){
qDebug() << query.value(0) << " "
<<query.value(1) << " "
<<query.value(2) << " "
<<query.value(3);
}
}