【Qt】SQLite——数据库介绍

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语法,事务,数据表和索引等。

他的特点主要是。

  1. 管理简单,甚至可以说不需要管理
  2. 操作简单,SQLite生成的数据文件可以在各个平台无缝连接
  3. 可以非常方便的以多种形式嵌入其他应用程序,如静态库,动态库等。
  4. 易于维护

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

  1. 添加SQLite数据库驱动,返回⼀个连接
C 复制代码
QSqlDatabase texDB = QSqlDatabase::addDatabase("QSQLITE");
  1. 功能:设置数据库文件的名称 name: 要连接的数据库的名称。对于SQLite,通常是数据库文件的路径;对于其他数据库系统,比如MySQL通常是数据库管理系统中数据库的名称。注意要使其生效,必须在打开连接之前设置数据库名称。或者,可以关闭连接,设置数据库名称,然后再次调用open()。
c 复制代码
void QSqlDatabase::setDatabaseName(const QString &name)
  1. 功能:打开数据库连接,即和数据库真正建立连接。返回值:连接成功连接返回true,否则返回false,注意:可以使用isopen()方法检测是否打开 。user:数据库用户名 。password: 数据库密码
c 复制代码
bool open();
bool open(const QString &user, const QString &password);
  1. 功能:关闭数据库连接,释放所有资源,并使与数据库⼀起使用的所有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)。

  1. 使用SQL查询和数据库db构造一个QSqlQuery对象。如果未指定db,或者db无效,则使用应用程序的默认数据库。如果查询不是空字符串,它将被执行。
c 复制代码
QSqlQuery::QSqlQuery(const QString &query = QString(), QSqlDatabase db = QSqlDatabase())
  1. 数据库表创建好之后,通过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 插入数据

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

  1. 检索结果中的下一条记录(如果有),并将查询定位在检索到的记录上。请注意,结果必须处于活动状态,isSelect()必须在调用此函数之前返回true,否则它将什么也不做并返回false。
    以下规则适用:
  • 如果结果当前位于第一条记录之前,例如在执行查询之后,立即尝试检索第一条记录。
  • 如果结果当前位于最后一条记录之后,则没有变化,并返回false。
  • 如果结果位于中间,则尝试检索下一条记录。
  • 如果无法检索到该记录,则结果位于最后一条记录之后,并返回false。如果成功检索到记录,则返回true。\
c 复制代码
bool QSqlQuery::next()
  1. 返回当前记录中字段索引的值。使用SELECT语句的文本从左到右对字段进行编号,例如字段0是名字,字段1是姓氏。不建议使用SELECT *,因为查询中的字段顺序未定义。如果字段索引不存在,如果查询处于非活动状态,或者如果查询位于无效记录上,则返回无效的QVariant。
c 复制代码
QVariant QSqlQuery::value(int index) const
  1. 这是一个重载函数。返回当前记录中名为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);
    }
}
相关推荐
流星白龙2 小时前
【Redis】4.基本全局命令
数据库·redis·缓存
王八八。3 小时前
Navicat 17破解版下载安装教程 附安装激活步骤(2026 最新版)
数据库·navicat
Jelena157795857924 小时前
电商运营分析数据比价接口实战:多平台价格监控与智能决策系统
java·大数据·数据库
流星白龙5 小时前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
凌虚6 小时前
基于 PostgreSQL WAL 构建 CDC 系统:原理与工程实现
数据库·后端·postgresql
BullSmall6 小时前
PostgreSQL 14 pg_dumpall 完整备份指南
数据库·postgresql·oracle
一只枫林7 小时前
MySQL内、外连接知识点汇总
java·前端·数据库
暮暮祈安7 小时前
Celery 新手入门指南
java·数据库·python·flask·httpx
xiaowang1234shs8 小时前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
Quincy_Freak8 小时前
银河麒麟 aarch64 环境下轻量 SQLite 管理方案实践:SQLiteGo 落地体验
数据库·sqlite·sqlitego