Qt 实现SQLite全部语法(增删改查、内置函数、高级语法)

news2024/10/7 16:25:30

Qt 实现SQLite全部语法

  • 【1】SQLite Qt界面设计
  • 【2】SQLite Qt数据库创建、打开、关闭、删除
  • 【3】SQLite Qt表格的创建
  • 【4】SQLite Qt表格的插入
  • 【5】SQLite Qt表格的查询
  • 【6】SQLite Qt表格的删除
  • 【7】SQLite Qt表格的更新
  • 【8】SQLite Qt表格的结构
  • 【9】SQLite Qt表格的修改
  • 【10】SQLite 常用内置函数举例
    • 1、计算表格行数
    • 2、计算表格某列最大值
    • 3、计算表格某列最小值
    • 4、计算表格某列平均值
    • 5、计算表格某列总和
    • 6、计算一个随机数
    • 7、计算绝对值
    • 8、字符串转化大小写
    • 9、计算字符串长度
    • 10、效果
  • 【11】SQLite 日期函数
  • 【12】SQLite LIKE和GLOB子句(通配符)
  • 【13】SQLite LIMIT子句 (限定行显示)
  • 【14】SQLite 表格排序 (升序、降序)
  • 【15】SQLite GROUP BY子句 (分组)
  • 【16】SQLite HAVING 子句(分组的条件)
  • 【17】SQLite DISTINCT 关键字(去重)
  • 【18】SQLite 交叉连接(CROSS JOIN)
  • 【19】SQLite 内连接(INNER JOIN)
  • 【20】SQLite 外连接(OUTER JOIN)
  • 【21】UNION 子句 (查询行不重复、重复)
  • 【22】SQLite 触发器(Trigger)
  • 【23】SQLite 视图(View)
  • 【24】SQLite 事务(Transaction)
  • 【25】SQLite 子查询或内部查询或嵌套查询
  • 【26】EXPLAIN (注释)


在这里插入图片描述


本节SQLite相关概念在鄙人个人公众号:👍Qt历险记👍
感兴趣的朋友可以关注下。
在这里插入图片描述


本次将SQLite在Qt中实现,方便用到的时候直接套模板,通过Qt信号与槽机制,将SQLite的语法基本全举例出来,欢迎留言交流。

注意在Qt中使用数据库添加如下:

# User self add
QT += sql

【1】SQLite Qt界面设计

界面都是一些按钮、文本框、表格等,代码中会涉及
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


【2】SQLite Qt数据库创建、打开、关闭、删除

查看Qt支持的数据库引擎

//数据库引擎
foreach(QString i ,QSqlDatabase::drivers())
{
    ui->textBrowser->append(i);
}

效果
在这里插入图片描述
打开数据库,并设置是数据库的相关参数

// 打开数据库
void MainWindow::on_pushButton_clicked()
{
    db = QSqlDatabase::addDatabase("QSQLITE","kali");
    db.setDatabaseName("C:\\aaa\\mysqlite.db");
    db.setHostName("localhost");
    db.setUserName("username");
    db.setPassword("password");
    ui->textBrowser_2->append("数据库的相关信息如下:");
    ui->textBrowser_2->append("db.port = " + QString::number(db.port()));
    ui->textBrowser_2->append("db.hostName = " + db.hostName());
    ui->textBrowser_2->append("db.password = " + db.password());
    ui->textBrowser_2->append("db.userName = " + db.userName());
    ui->textBrowser_2->append("db.driverName = " + db.driverName());
    ui->textBrowser_2->append("db.databaseName = " + db.databaseName());
    ui->textBrowser_2->append("db.connectOptions = " + db.connectOptions());
    ui->textBrowser_2->append("db.connectionName = " + db.connectionName());
    if (db.isValid()) // 数据库存在
    {
        if (db.open())
        {
            QMessageBox::information(NULL,"打开数据库","数据库"+db.databaseName()+"打开成功!  数据库引擎: "+db.driverName(),QMessageBox::Close);
        }
        else {
            QMessageBox::critical(NULL,"打开数据库","数据库"+db.databaseName()+"打开失败:"+db.lastError().text(),QMessageBox::Close);
            return;
        }
    }
}

运行效果
在这里插入图片描述


删除和关闭数据库

// 数据库删除
void MainWindow::on_pushButton_5_clicked()
{
    //db.removeDatabase("kali");
    // 从应用程序中删除数据库对象
    QSqlDatabase::removeDatabase(db.connectionName());

    // 删除数据库文件
    QFile::remove(db.databaseName());
}
// 关闭数据库
void MainWindow::on_pushButton_7_clicked()
{
    db.close();
}

【3】SQLite Qt表格的创建

这里使用QTableWidget组件显示表内容
在Qt中要使用查询语句,需要将数据库对象连接如下:

QSqlQuery db_query(db);
数据类型:
INTEGER 
TEXT 
CHAR(15)
PRIMARY KEY :主键
AUTOINCREMENT:自增
check(条件):检查
DEFAULT  value:默认值
UNIQUE : 唯一约束,值不能相同
NOT NULL:不能为空
// 创建表
void MainWindow::on_pushButton_2_clicked()
{
    ui->tableWidget->setRowCount(1000);
    ui->tableWidget->setColumnCount(5);
    ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"id"<<"name"<<"age"<<"qq"<<"phone");
    ui->tableWidget->resizeRowsToContents();
    ui->tableWidget->resizeColumnsToContents();
    ui->tableWidget->setColumnWidth(0,50);
    ui->tableWidget->setColumnWidth(1,60);
    ui->tableWidget->setColumnWidth(2,50);
    ui->tableWidget->setColumnWidth(3,100);
    ui->tableWidget->setColumnWidth(4,100);
    ui->tableWidget->setStyleSheet("QTableView {border:2px,solid blue;}");

    QSqlQuery db_query(db);
    ui->textBrowser_2->append("\r\n查询类的相关信息如下:");
    ui->textBrowser_2->append("db_query.size = " + QString::number(db_query.size()));
    ui->textBrowser_2->append("db_query.lastQuery = " + db_query.lastQuery());
    ui->textBrowser_2->append("db_query.lastInsertId = " + db_query.lastInsertId().toString());
    ui->textBrowser_2->append("db_query.executedQuery = " + db_query.executedQuery());

    if (db_query.exec("CREATE TABLE student (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER NOT NULL check(age > 0), qq CHAR(15) NOT NULL UNIQUE, phone INTEGER DEFAULT  10086)")){
        QMessageBox::information(NULL,"创建表","创建成功:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"创建表","表创建失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果
在这里插入图片描述


【4】SQLite Qt表格的插入

在Qt中插入数据,最好不要使用通配符*,指定列名比较好,注意插入的数据匹配数据类型。

// 表格插入
void MainWindow::on_pushButton_3_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("INSERT INTO student (id,name,age,qq,phone) VALUES (%1,'%2',%3,'%4',%5)").arg(ui->lineEdit_id->text()).arg(ui->lineEdit_name->text()).arg(ui->lineEdit_age->text()).arg(ui->lineEdit_qq->text()).arg(ui->lineEdit_phone->text()))){
        QMessageBox::information(NULL,"插入表","插入成功:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"插入表","插入失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述


【5】SQLite Qt表格的查询

这里查询的时候以 ORDER BY id ASC升序显示(从小到大),降序时使用DESC(大到小)。

// 表格查询 升序
void MainWindow::on_pushButton_4_clicked()
{
    QSqlQuery db_query(db);
    int row = 0;
    if (db_query.exec("SELECT id,name,age,qq,phone FROM student  ORDER BY id ASC"))
    {
        QMessageBox::information(NULL,"查询表","查询成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id = db_query.value(0).toInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toInt();
            QString qq = db_query.value(3).toString();
            quint64 phone = db_query.value(4).toULongLong();
            ui->tableWidget->setItem(row,0,new QTableWidgetItem(QString::number(id)));
            ui->tableWidget->setItem(row,1,new QTableWidgetItem(name));
            ui->tableWidget->setItem(row,2,new QTableWidgetItem(QString::number(age)));
            ui->tableWidget->setItem(row,3,new QTableWidgetItem(qq));
            ui->tableWidget->setItem(row,4,new QTableWidgetItem(QString::number(phone)));
            row += 1;   //行数动态增加
        }
    }
    else {
        QMessageBox::critical(NULL,"查询表","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述
在这里插入图片描述


【6】SQLite Qt表格的删除

// 删除表
void MainWindow::on_pushButton_6_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("DROP TABLE IF EXISTS student")){
        QMessageBox::information(NULL,"删除表","删除成功+命令:"+db_query.lastQuery(),QMessageBox::Close);
        ui->tableWidget->clearContents();
    }
    else{
        QMessageBox::critical(NULL,"插入表","插入失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述


【7】SQLite Qt表格的更新

主要是更新表格的列值,可以是单个也可以是全部。

// 修改表  修改名字和年龄 以id作为条件
void MainWindow::on_pushButton_8_clicked()
{
    QSqlQuery db_query(db);
    if (ui->lineEdit_id->text().isEmpty())
    {
        QMessageBox::warning(NULL,"id为空"," id是条件,不能为空!!!",QMessageBox::Close);
        return;
    }

    if (!ui->lineEdit_name->text().isEmpty() && !ui->lineEdit_age->text().isEmpty())
    {
        if (db_query.exec(QString("UPDATE student SET name='%1', age=%2 WHERE id=%3").arg(ui->lineEdit_name->text()).arg(ui->lineEdit_age->text()).arg(ui->lineEdit_id->text()))){
            QMessageBox::information(NULL,"修改表","修改name,age成功+命令:"+db_query.lastQuery(),QMessageBox::Close);
        }
        else{
            QMessageBox::critical(NULL,"修改表","修改name,age失败:" +db_query.lastError().text() ,QMessageBox::Close);
            return;
        }
    }
    else if (!ui->lineEdit_name->text().isEmpty() && ui->lineEdit_age->text().isEmpty())
    {
        if (db_query.exec(QString("UPDATE student SET name='%1' WHERE id=%2").arg(ui->lineEdit_name->text()).arg(ui->lineEdit_id->text()))){
            QMessageBox::information(NULL,"修改表","修改name成功+命令:"+db_query.lastQuery(),QMessageBox::Close);
        }
        else{
            QMessageBox::critical(NULL,"修改表","修改name失败:" +db_query.lastError().text() ,QMessageBox::Close);
            return;
        }
    }
    else if (ui->lineEdit_name->text().isEmpty() && !ui->lineEdit_age->text().isEmpty())
    {
        if (db_query.exec(QString("UPDATE student SET age=%1 WHERE id=%2").arg(ui->lineEdit_age->text()).arg(ui->lineEdit_id->text()))){
            QMessageBox::information(NULL,"修改表","修改name成功+命令:"+db_query.lastQuery(),QMessageBox::Close);
        }
        else{
            QMessageBox::critical(NULL,"修改表","修改name失败:" +db_query.lastError().text() ,QMessageBox::Close);
            return;
        }
    }
    else
    {
            QMessageBox::critical(NULL,"修改表格","修改name,age 失败" + db_query.lastError().text() ,QMessageBox::Close);
            return;
    }
}

效果
在这里插入图片描述
在这里插入图片描述


【8】SQLite Qt表格的结构

// 表结构
void MainWindow::on_pushButton_9_clicked()
{
   QSqlQuery db_query(db);
   QStringList tables = db.tables(); // 获取所有表格的名称
   for (int i = 0; i < tables.size(); i++) {
       ui->textBrowser_2->append(QString("表名: %1").arg(tables.at(i)));
   }

    // 循环遍历结果集并打印表结构信息
   ui->textBrowser_2->append(QString("\r\n表的结构如下:"));
   db_query.exec("SELECT SQLITE_VERSION()");
   while (db_query.next()) {
       QString version = db_query.value(0).toString();
       ui->textBrowser_2->append(QString("SQLITE version: %1").arg(version));
   }
   if (tables.contains("student")) {
       db_query.exec("PRAGMA table_info(student)");
       while (db_query.next()) {
           QString index = db_query.value(0).toString();
           QString name = db_query.value(1).toString();
           QString type = db_query.value(2).toString();
           qDebug() <<" index = "<<index<<  " Column Name:" << name << ", Type:" << type;
           ui->textBrowser_2->append(QString("Column Name: %1 , Type:%2").arg(name).arg(type));
       }
   }
}

效果
在这里插入图片描述


【9】SQLite Qt表格的修改

// 表格新增列
void MainWindow::on_pushButton_10_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("ALTER TABLE student ADD age INTEGER")){
        QMessageBox::information(NULL,"表格新增列","新增列成功+命令:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::information(NULL,"表格新增列","新增列失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述
在这里插入图片描述


【10】SQLite 常用内置函数举例

1、计算表格行数

// 计算数据库表格行数
void MainWindow::on_pushButton_12_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT count(*) FROM student"))
    {
        while (db_query.next()) {
            QString rowCount = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery()+";    表格行数 = "+rowCount);
        }
    }
}

2、计算表格某列最大值

// 计算表格最大值
void MainWindow::on_pushButton_13_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT max(id) FROM student"))
    {
        while (db_query.next()) {
            QString max = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id列的最大值是 = "+max);
        }
    }
}

3、计算表格某列最小值

// 计算表格最小值
void MainWindow::on_pushButton_14_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT min(id) FROM student"))
    {
        while (db_query.next()) {
            QString min = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id列的最小值是 = "+min);
        }
    }
}

4、计算表格某列平均值

// 计算表格某列平均值
void MainWindow::on_pushButton_15_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT avg(age) FROM student"))
    {
        while (db_query.next()) {
            QString avg = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   age列的平均值是 = "+avg);
        }
    }
}

5、计算表格某列总和

// 计算表格某列总和
void MainWindow::on_pushButton_16_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT sum(age) FROM student"))
    {
        while (db_query.next()) {
            QString sum = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   age列的求和是 = "+sum);
        }
    }
}

6、计算一个随机数

// 计算一个随机数
void MainWindow::on_pushButton_18_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT random() AS random"))
    {
        while (db_query.next()) {
            QString random = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   random = "+random);
        }
    }
}

7、计算绝对值

// 计算绝对值
void MainWindow::on_pushButton_17_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT abs(5),abs(-5),abs(NULL),abs('ABC')"))
    {
        while (db_query.next()) {
            QString abs1 = db_query.value(0).toString();
            QString abs2 = db_query.value(1).toString();
            QString abs3 = QString::number(db_query.value(2).toInt());
            QString abs4 = QString::number(db_query.value(3).toDouble());
            ui->textBrowser_3->append(db_query.lastQuery() +";   abs1 = "+abs1 +", adb2 = "+abs2+", abs3 = "+abs3+" ,abs4 = "+abs4);
        }
    }
}

8、字符串转化大小写

// 字符串转化大写
void MainWindow::on_pushButton_20_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT upper('myname')"))
    {
        while (db_query.next()) {
            QString upper = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   upper(myname) = "+upper);
        }
    }
}
// 字符串转化小写
void MainWindow::on_pushButton_19_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT lower('MYNAME')"))
    {
        while (db_query.next()) {
            QString upper = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   lower(MYNAME) = "+upper);
        }
    }
}

9、计算字符串长度

// 计算字符串长度
void MainWindow::on_pushButton_21_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT name, length(name) FROM student"))
    {
        while (db_query.next()) {
            QString name = db_query.value(0).toString();
            quint32 len = db_query.value(1).toUInt();
            ui->textBrowser_3->append(db_query.lastQuery() +";   name = "+name+" len = "+QString::number(len));
        }
    }
}

10、效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


【11】SQLite 日期函数

这里只是举例了部分,根据实际需要进行修改即可

// date 当前日期
void MainWindow::on_pushButton_24_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT date('now')"))
    {
        while (db_query.next()) {
            QString date = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   date = "+date);
        }
    }
    if (db_query.exec("SELECT date()"))
    {
        while (db_query.next()) {
            QString date = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   date = "+date);
        }
    }
    // 计算当前月份的最后一天:
    if (db_query.exec("SELECT date('now','start of month','+1 month','-1 day')"))
    {
        while (db_query.next()) {
            QString date = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   date = "+date);
        }
    }
    // 给定 UNIX 时间戳 1092941466 的日期和时间:
    if (db_query.exec("SELECT datetime()"))
    {
        while (db_query.next()) {
            QString datetime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   datetime = "+datetime);
        }
    }
    if (db_query.exec("SELECT datetime(1092941466, 'unixepoch')"))
    {
        while (db_query.next()) {
            QString datetime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   datetime = "+datetime);
        }
    }
    // 计算给定 UNIX 时间戳 1092941466 相对本地时区的日期和时间:
    if (db_query.exec("SELECT datetime(1092941466, 'unixepoch', 'localtime')"))
    {
        while (db_query.next()) {
            QString datetime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   datetime = "+datetime);
        }
    }
    // 一周中的第几天,0-6 (0 is Sunday)
    if (db_query.exec("SELECT strftime('%w','now')"))
    {
        while (db_query.next()) {
            QString strftime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   strftime = "+strftime + "【 '%w' 一周中的第几天,0-6 (0 is Sunday)】");
        }
    }
    if (db_query.exec("SELECT strftime('%s', 'now')"))
    {
        while (db_query.next()) {
            QString strftime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   strftime = "+strftime + "【 \"%s\"	从 1970-01-01 算起的秒数】");
        }
    }
    if (db_query.exec("SELECT strftime('%Y-%m-%d %H', 'now')"))
    {
        while (db_query.next()) {
            QString strftime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   strftime = "+strftime);
        }
    }

    // 计算从 2004 年某一特定时刻以来的秒数:
    if (db_query.exec("SELECT strftime('%s','now') - strftime('%s','2004-01-01 02:34:56')"))
    {
        while (db_query.next()) {
            QString strftime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   strftime = "+strftime + "【 \"%s\"	从 1970-01-01 算起的秒数】");
        }
    }
    if (db_query.exec("SELECT strftime('%Y年%m月%d日 %H时:%M分:%S秒  周%w')"))
    {
        while (db_query.next()) {
            QString strftime = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   strftime = "+strftime +"\r\n");
        }
    }

    // 计算当年 10 月的第一个星期二的日期:
    if (db_query.exec("SELECT date('now','start of year','+9 months','weekday 2')"))
    {
        while (db_query.next()) {
            QString date = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   date = "+date);
        }
    }

    // 在 UTC 与本地时间值之间进行转换,当格式化日期时,使用 utc 或 localtime 修饰符,如下所示:
    if (db_query.exec("SELECT time('12:00', 'localtime')"))
    {
        while (db_query.next()) {
            QString time = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   time = "+time);
        }
    }
    // 在 UTC 与本地时间值之间进行转换,当格式化日期时,使用 utc 或 localtime 修饰符,如下所示:
    if (db_query.exec("SELECT time('12:00', 'utc')"))
    {
        while (db_query.next()) {
            QString time = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   time = "+time);
        }
    }
}

效果

SELECT date('now');   date = 2023-06-24
SELECT date();   date = 2023-06-24
SELECT date('now','start of month','+1 month','-1 day');   date = 2023-06-30
SELECT datetime();   datetime = 2023-06-24 01:16:14
SELECT datetime(1092941466, 'unixepoch');   datetime = 2004-08-19 18:51:06
SELECT datetime(1092941466, 'unixepoch', 'localtime');   datetime = 2004-08-20 02:51:06
SELECT strftime('%w','now');   strftime = 6'%w' 一周中的第几天,0-6 (0 is Sunday)】
SELECT strftime('%s', 'now');   strftime = 1687569374"%s"1970-01-01 算起的秒数】
SELECT strftime('%Y-%m-%d %H', 'now');   strftime = 2023-06-24 01
SELECT strftime('%s','now') - strftime('%s','2004-01-01 02:34:56');   strftime = 614644878"%s"1970-01-01 算起的秒数】
SELECT strftime('%Y年%m月%d日 %H时:%M分:%S秒  周%w');   strftime = 2023年06月24日 01时:16分:14秒  周6

SELECT date('now','start of year','+9 months','weekday 2');   date = 2023-10-03
SELECT time('12:00', 'localtime');   time = 20:00:00
SELECT time('12:00', 'utc');   time = 04:00:00

【12】SQLite LIKE和GLOB子句(通配符)

LIKE

// 百分号 (%)下划线 (_) 百分号(%)代表零个、一个或多个数字或字符。下划线(_)代表一个单一的数字或字符。这些符号可以被组合使用。
void MainWindow::on_pushButton_22_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT *FROM student WHERE name LIKE '%1'").arg(ui->lineEdit_search->text())))
    {
        while (db_query.next()) {
            QString id = db_query.value(0).toString();
            QString name = db_query.value(1).toString();
            QString age = db_query.value(2).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id = "+id +" name = "+name+" age = "+age);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

GLOB

// 星号(*)代表零个、一个或多个数字或字符。问号(?)代表一个单一的数字或字符。这些符号可以被组合使用。
void MainWindow::on_pushButton_25_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT *FROM student WHERE name GLOB '%1'").arg(ui->lineEdit_search->text())))
    {
        while (db_query.next()) {
            QString id = db_query.value(0).toString();
            QString name = db_query.value(1).toString();
            QString age = db_query.value(2).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id = "+id +" name = "+name+" age = "+age);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果

LIKE

在这里插入图片描述
在这里插入图片描述

GLOB

在这里插入图片描述
在这里插入图片描述


【13】SQLite LIMIT子句 (限定行显示)

// SQLite 的 LIMIT 子句用于限制由 SELECT 语句返回的数据数量。
void MainWindow::on_pushButton_23_clicked()
{
    QSqlQuery db_query(db);
    // Limit 提取的行数 Offet 从第一行开始跳过多少行
    if (db_query.exec(QString("SELECT * FROM student LIMIT %1 OFFSET %2").arg(ui->lineEdit_search->text().split('/').at(0)).arg(ui->lineEdit_search->text().split('/').at(1))))
    {
        while (db_query.next()) {
            QString id = db_query.value(0).toString();
            QString name = db_query.value(1).toString();
            QString age = db_query.value(2).toString();
            QString qq = db_query.value(3).toString();
            QString phone = db_query.value(4).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id = "+id +" name = "+name+" age = "+age +" qq = "+qq +" phone = "+phone);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述
在这里插入图片描述


【14】SQLite 表格排序 (升序、降序)

// 表格排序
void MainWindow::on_pushButton_26_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT * FROM student ORDER BY %1").arg(ui->lineEdit_search->text())))
    {
        while (db_query.next()) {
            QString id = db_query.value(0).toString();
            QString name = db_query.value(1).toString();
            QString age = db_query.value(2).toString();
            QString qq = db_query.value(3).toString();
            quint64 phone = db_query.value(4).toULongLong();
            ui->textBrowser_3->append(db_query.lastQuery() +";   id = "+id +" name = "+name+" age = "+age+" qq = "+qq+" phone = "+phone);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果

降序

在这里插入图片描述

升序

在这里插入图片描述


【15】SQLite GROUP BY子句 (分组)

// 在 SELECT 语句中,GROUP BY 子句必须放在 WHERE 子句之后,放在 ORDER BY 子句之前。
void MainWindow::on_pushButton_30_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT name, SUM(age) FROM student GROUP BY name ORDER BY name DESC")))
    {
        while (db_query.next()) {
            QString name = db_query.value(0).toString();
            QString sum = db_query.value(1).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   name = "+name +" sum = "+sum);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果 降序显示name
在这里插入图片描述


【16】SQLite HAVING 子句(分组的条件)

// WHERE 子句在所选列上设置条件,而 HAVING 子句则在由 GROUP BY 子句创建的分组上设置条件。
void MainWindow::on_pushButton_29_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT * FROM student GROUP BY name HAVING length(name) < 2")))
    {
        while (db_query.next()) {
            QString name = db_query.value(1).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   name = "+name);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }

    if (db_query.exec(QString("SELECT * FROM student GROUP BY name HAVING length(name) >= 2")))
    {
        while (db_query.next()) {
            QString name = db_query.value(1).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   name = "+name);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述


【17】SQLite DISTINCT 关键字(去重)

// 在一个表中有多个重复的记录。当提取这样的记录时,DISTINCT 关键字就显得特别有意义,它只获取唯一一次记录,而不是获取重复记录。
void MainWindow::on_pushButton_33_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec(QString("SELECT DISTINCT name FROM student")))  // 查询没有重复的name
    {
        while (db_query.next()) {
            QString name = db_query.value(0).toString();
            ui->textBrowser_3->append(db_query.lastQuery() +";   name = "+name);
        }
    }
    else{
        QMessageBox::information(NULL,"查询","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

效果
在这里插入图片描述
在这里插入图片描述


【18】SQLite 交叉连接(CROSS JOIN)

交叉连接往往在两个表,所以这里我们在创建一个教师表。

//=======老师表创建======
void MainWindow::on_pushButton_28_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("CREATE TABLE teacher (id_t INTEGER,name_t TEXT,age_t INTEGER)")){
        QMessageBox::information(NULL,"创建表","创建成功:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"创建表","表创建失败:" + db_query.lastError().text(),QMessageBox::Close);
    }


    if (db_query.exec(QString("INSERT INTO teacher (id_t,name_t,age_t) VALUES (%1,'%2',%3)").arg(ui->lineEdit_id->text()).arg(ui->lineEdit_name->text()).arg(ui->lineEdit_age->text()))){
        QMessageBox::information(NULL,"插入表","插入成功:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"插入表","插入失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }

    if (db_query.exec("SELECT id_t,name_t,age_t FROM teacher ORDER BY id_t ASC"))
    {
        QMessageBox::information(NULL,"查询表","查询成功:"+db_query.lastQuery(),QMessageBox::Close);

        int row = 9;
        while (db_query.next()) {
            int id = db_query.value(0).toInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toInt();
            ui->tableWidget->setItem(row,0,new QTableWidgetItem(QString::number(id)));
            ui->tableWidget->setItem(row,1,new QTableWidgetItem(name));
            ui->tableWidget->setItem(row,2,new QTableWidgetItem(QString::number(age)));
            row += 1;   //行数动态增加
        }
    }
    else {
        QMessageBox::critical(NULL,"查询表","查询失败:" +db_query.lastError().text() ,QMessageBox::Close);
        return;
    }
}

交叉连接

// 交叉连接(CROSS JOIN)把第一个表的每一行与第二个表的每一行进行匹配。如果两个输入表分别有 x 和 y 列,则结果表有 x*y 列。
// 由于交叉连接(CROSS JOIN)有可能产生非常大的表,使用时必须谨慎,只在适当的时候使用它们。
void MainWindow::on_pushButton_31_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT id_t, name, age_t FROM student CROSS JOIN teacher")){
        QMessageBox::information(NULL,"交叉连接","交叉连接成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id) +" name = " +name +" age_t = "+QString::number(age));
        }
    }
    else{
        QMessageBox::critical(NULL,"交叉连接","交叉连接失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果

学生表

在这里插入图片描述

老师表

在这里插入图片描述
交叉连接效果
在这里插入图片描述
在这里插入图片描述

交叉连接会增大行数,学生表的名字对应表的行数,学生表一个名字对应教师表有多少行就对应多少次。


【19】SQLite 内连接(INNER JOIN)

// 内连接(INNER JOIN)根据连接谓词结合两个表(table1 和 table2)的列值来创建一个新的结果表。
void MainWindow::on_pushButton_32_clicked()
{
    QSqlQuery db_query(db);
    // 在id 相等时 连接成一个新表
    if (db_query.exec("SELECT id_t, name, age_t FROM student INNER JOIN  teacher ON student.id = teacher.id_t")){
        QMessageBox::information(NULL,"内连接","内连接成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id) +" name = " +name +" age_t = "+QString::number(age));
        }
    }
    else{
        QMessageBox::critical(NULL,"内连接","内连接失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果
学生表
在这里插入图片描述
老师表
在这里插入图片描述
在这里插入图片描述


【20】SQLite 外连接(OUTER JOIN)

// 外连接(OUTER JOIN)是内连接(INNER JOIN)的扩展。虽然 SQL 标准定义了三种类型的外连接:LEFT、RIGHT、FULL,但 SQLite 只支持 左外连接(LEFT OUTER JOIN)。
void MainWindow::on_pushButton_34_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT id_t, name, age_t FROM student LEFT OUTER JOIN  teacher ON student.id = teacher.id_t")){
        QMessageBox::information(NULL,"外连接","外连接成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id_t = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id_t) +" name = " +name +" age_t = "+QString::number(age));
        }
    }
    else{
        QMessageBox::critical(NULL,"外连接","外连接失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果
好像只有第一个有效
在这里插入图片描述


【21】UNION 子句 (查询行不重复、重复)

SQLite的 UNION 子句/运算符用于合并两个或多个 SELECT 语句的结果,不返回任何重复的行。
为了使用 UNION,每个 SELECT 被选择的列数必须是相同的,相同数目的列表达式,相同的数据类型,并确保它们有相同的顺序,但它们不必具有相同的长度。

// SQLite的 UNION 子句/运算符用于合并两个或多个 SELECT 语句的结果,不返回任何重复的行。
// UNION ALL 运算符用于结合两个 SELECT 语句的结果,包括重复行。
void MainWindow::on_pushButton_35_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT id_t, name, age_t FROM student INNER JOIN teacher \
                      ON student.id = teacher.id_t \
                 UNION \
                   SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher \
                      ON student.id = teacher.id_t")){
        QMessageBox::information(NULL,"UNION 子句","UNION 子句成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id_t = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id_t) +" name = " +name +" age_t = "+QString::number(age));
        }
    }
    else{
        QMessageBox::critical(NULL,"UNION 子句","UNION 子句失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec("SELECT id_t, name, age_t FROM student INNER JOIN teacher \
        ON student.id = teacher.id_t \
        UNION ALL\
        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher \
        ON student.id = teacher.id_t"))
    {
        QMessageBox::information(NULL,"UNION 子句","UNION 子句成功:"+db_query.lastQuery(),QMessageBox::Close);

        while (db_query.next()) {
            int id_t = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id_t) +" name = " +name +" age_t = "+QString::number(age));
        }
    }
    else{
    QMessageBox::critical(NULL,"UNION 子句","UNION 子句失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果
学生表
在这里插入图片描述
老师表
在这里插入图片描述

SELECT id_t, name, age_t FROM student INNER JOIN teacher ON student.id = teacher.id_t                  
	UNION  
SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher ON student.id = teacher.id_t;   
`id_t = 0 name = 4 age_t = 0`
SELECT id_t, name, age_t FROM student INNER JOIN teacher ON student.id = teacher.id_t                  
	UNION                    
SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher ON student.id = teacher.id_t;   
`id_t = 0 name = 小红花给你 age_t = 0`
SELECT id_t, name, age_t FROM student INNER JOIN teacher                       ON student.id = teacher.id_t                  
	UNION                    
SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher                       ON student.id = teacher.id_t;   
`id_t = 0 name = 李不白 age_t = 0`
SELECT id_t, name, age_t FROM student INNER JOIN teacher                       ON student.id = teacher.id_t                  
	UNION                    
SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher                       ON student.id = teacher.id_t;   
`id_t = 1 name = 李不白 age_t = 23`
SELECT id_t, name, age_t FROM student INNER JOIN teacher                       ON student.id = teacher.id_t                  
	UNION                    
SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher                       ON student.id = teacher.id_t;   
`id_t = 2 name = 3 age_t = 22`




SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 1 name = 李不白 age_t = 23`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 2 name = 3 age_t = 22`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 1 name = 李不白 age_t = 23`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 2 name = 3 age_t = 22`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 0 name = 4 age_t = 0`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 0 name = 小红花给你 age_t = 0`
SELECT id_t, name, age_t FROM student INNER JOIN teacher         ON student.id = teacher.id_t         UNION ALL        SELECT id_t, name, age_t FROM student LEFT OUTER JOIN teacher         ON student.id = teacher.id_t;   
`id_t = 0 name = 李不白 age_t = 0`

【22】SQLite 触发器(Trigger)

比作:中断,信号


SQLite 的触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。
以下是关于SQLite的触发器的要点:
SQLite 触发器(Trigger)是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。以下是关于 SQLite 的触发器(Trigger)的要点:
SQLite 的触发器(Trigger)可以指定在特定的数据库表发生 DELETE、INSERT 或 UPDATE 时触发,或在一个或多个指定表的列发生更新时触发。
SQLite 只支持 FOR EACH ROW 触发器(Trigger),没有 FOR EACH STATEMENT 触发器(Trigger)。因此,明确指定 FOR EACH ROW 是可选的。
WHEN 子句和触发器(Trigger)动作可能访问使用表单 NEW.column-name 和 OLD.column-name 的引用插入、删除或更新的行元素,其中 column-name 是从与触发器关联的表的列的名称。
如果提供 WHEN 子句,则只针对 WHEN 子句为真的指定行执行 SQL 语句。如果没有提供 WHEN 子句,则针对所有行执行 SQL 语句。
BEFORE 或 AFTER 关键字决定何时执行触发器动作,决定是在关联行的插入、修改或删除之前或者之后执行触发器动作。
当触发器相关联的表删除时,自动删除触发器(Trigger)。
要修改的表必须存在于同一数据库中,作为触发器被附加的表或视图,且必须只使用 tablename,而不是 database.tablename。
一个特殊的 SQL 函数 RAISE() 可用于触发器程序内抛出异常。

// SQLite 触发器(Trigger)是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。
void MainWindow::on_pushButton_36_clicked()
{
      QSqlQuery db_query(db);
      if (db_query.exec("CREATE TABLE AUDIT(EMP_ID INTEGER ,ENTRY_DATE TEXT)")){
          QMessageBox::information(NULL,"Trigger","Trigger成功:"+db_query.lastQuery(),QMessageBox::Close);
      }
      else{
          QMessageBox::critical(NULL,"Trigger","Trigger失败:" + db_query.lastError().text(),QMessageBox::Close);
      }

      if (db_query.exec("CREATE TRIGGER audit_log AFTER INSERT\
                        ON student\
                        BEGIN\
                           INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, datetime('now'));\
                        END")){
          QMessageBox::information(NULL,"Trigger","Trigger成功:"+db_query.lastQuery(),QMessageBox::Close);

          while (db_query.next()) {
              int id_t = db_query.value(0).toUInt();
              QString name = db_query.value(1).toString();
              int age = db_query.value(2).toUInt();
              ui->textBrowser_4->append(db_query.lastQuery() +";   id_t = "+QString::number(id_t) +" name = " +name +" age_t = "+QString::number(age));
          }
      }
      else{
          QMessageBox::critical(NULL,"Trigger","Trigger失败:" + db_query.lastError().text(),QMessageBox::Close);
      }

    if (db_query.exec("SELECT EMP_ID, ENTRY_DATE FROM AUDIT")){
        QMessageBox::information(NULL,"Trigger","Trigger成功:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int id_t = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            ui->textBrowser_4->append(db_query.lastQuery() +";   EMP_ID = "+QString::number(id_t) +" ENTRY_DATE = " +name);
        }
    }
    else{
        QMessageBox::critical(NULL,"Trigger","Trigger失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果,在学生表插入时,会自动保存触发表
插入id = 2时
在这里插入图片描述

在这里插入图片描述


【23】SQLite 视图(View)

视图(View)只不过是通过相关的名称存储在数据库中的一个 SQLite 语句。视图(View)实际上是一个以预定义的 SQLite 查询形式存在的表的组合。
视图(View)可以包含一个表的所有行或从一个或多个表选定行。视图(View)可以从一个或多个表创建,这取决于要创建视图的 SQLite 查询。、
视图(View)是一种虚表,允许用户实现以下几点:
用户或用户组查找结构数据的方式更自然或直观。
限制数据访问,用户只能看到有限的数据,而不是完整的表。
汇总各种表中的数据,用于生成报告。

SQLite 视图是只读的,因此可能无法在视图上执行 DELETE、INSERT 或 UPDATE 语句。但是可以在视图上创建一个触发器,当尝试 DELETE、INSERT 或 UPDATE 视图时触发,需要做的动作在触发器内容中定义。

//  视图(View)只不过是通过相关的名称存储在数据库中的一个 SQLite 语句。视图(View)实际上是一个以预定义的 SQLite 查询形式存在的表的组合。
void MainWindow::on_pushButton_37_clicked()
{
        QSqlQuery db_query(db);
        if (db_query.exec("CREATE VIEW student_VIEW AS SELECT id, name, age FROM  student")){
            QMessageBox::information(NULL,"视图(View)","视图(View)成功:"+db_query.lastQuery(),QMessageBox::Close);
        }
        else{
            QMessageBox::critical(NULL,"视图(View)","视图(View)失败:" + db_query.lastError().text(),QMessageBox::Close);
        }

        if (db_query.exec("SELECT * FROM student_VIEW")){
                QMessageBox::information(NULL,"视图(View)","视图(View)成功:"+db_query.lastQuery(),QMessageBox::Close);

                while (db_query.next()) {
                int id = db_query.value(0).toUInt();
                QString name = db_query.value(1).toString();
                int age = db_query.value(2).toUInt();
                ui->textBrowser_4->append(db_query.lastQuery() +";   id = "+QString::number(id) +" name = " +name +" age =  "+QString::number(age));
            }
        }
        else{
              QMessageBox::critical(NULL,"视图(View)","视图(View)失败:" + db_query.lastError().text(),QMessageBox::Close);
        }

        if (db_query.exec("DROP VIEW student_VIEW")){
            QMessageBox::information(NULL,"视图(View)","视图(View)成功:"+db_query.lastQuery(),QMessageBox::Close);
        }
        else{
            QMessageBox::critical(NULL,"视图(View)","视图(View)失败:" + db_query.lastError().text(),QMessageBox::Close);
        }
}

效果
在这里插入图片描述


【24】SQLite 事务(Transaction)

事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成。
事务(Transaction)是指一个或多个更改数据库的扩展。例如,如果您正在创建一个记录或者更新一个记录或者从表中删除一个记录,那么您正在该表上执行事务。重要的是要控制事务以确保数据的完整性和处理数据库错误。
实际上,您可以把许多的 SQLite 查询联合成一组,把所有这些放在一起作为事务的一部分进行执行。


事务的属性 事务(Transaction)具有以下四个标准属性,通常根据首字母缩写为 ACID:
原子性(Atomicity):确保工作单位内的所有操作都成功完成,否则,事务会在出现故障时终止,之前的操作也会回滚到以前的状态。
一致性(Consistency):确保数据库在成功提交的事务上正确地改变状态。
隔离性(Isolation):使事务操作相互独立和透明。
持久性(Durability):确保已提交事务的结果或效果在系统发生故障的情况下仍然存在。


事务控制
使用下面的命令来控制事务:
BEGIN TRANSACTION:开始事务处理。
COMMIT:保存更改,或者可以使用 ENDTRANSACTION 命令。
ROLLBACK:回滚所做的更改。
事务控制命令只与 DML 命令 INSERT、UPDATE 和DELETE 一起使用。他们不能在创建表或删除表时使用,因为这些操作在数据库中是自动提交的。

// 事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成。
void MainWindow::on_pushButton_38_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("BEGIN")){     // 开始事务
    QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:" + db_query.lastQuery(),QMessageBox::Close);
    }
    else{
    QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
    if (db_query.exec(QString("DELETE FROM student WHERE age = %1").arg(ui->lineEdit->text().toUInt()))){
        QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:" + db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec("SELECT age FROM student")){
            QMessageBox::information(NULL,"语句","命令:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int age = db_query.value(0).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";  age =  "+QString::number(age));
        }
    }

    if (db_query.exec("ROLLBACK")){  // 撤销以上操作
    QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:" + db_query.lastQuery(),QMessageBox::Close);
    }
    else{
    QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    //==========================================保存更改=====================================
    if (db_query.exec("BEGIN")){        // 开始事务
        QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:" + db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec(QString("DELETE FROM student WHERE age = %1").arg(ui->lineEdit->text().toUInt()))){
        QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:" + db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }


    if (db_query.exec("COMMIT")){ // 提交事务
        QMessageBox::information(NULL,"事务(Transaction)","事务(Transaction)成功:"+db_query.lastQuery(),QMessageBox::Close);
    }
    else{
        QMessageBox::critical(NULL,"事务(Transaction)","事务(Transaction)失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec("SELECT age FROM student")){
            QMessageBox::information(NULL,"语句","命令:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int age = db_query.value(0).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";  age =  "+QString::number(age));
        }
    }
}

效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
22被删除
在这里插入图片描述


【25】SQLite 子查询或内部查询或嵌套查询

子查询或内部查询或嵌套查询是在另一个 SQLite 查询内嵌入在 WHERE 子句中的查询。
使用子查询返回的数据将被用在主查询中作为条件,以进一步限制要检索的数据。
子查询可以与 SELECT、INSERT、UPDATE 和 DELETE 语句一起使用,可伴随着使用运算符如 =、<、>、>=、<=、IN、BETWEEN 等。
以下是子查询必须遵循的几个规则:
子查询必须用括号括起来。
子查询在 SELECT 子句中只能有一个列,除非在主查询中有多列,与子查询的所选列进行比较。
ORDER BY 不能用在子查询中,虽然主查询可以使用 ORDER BY。可以在子查询中使用 GROUP BY,功能与 ORDER BY 相同。
子查询返回多于一行,只能与多值运算符一起使用,如 IN 运算符。
BETWEEN 运算符不能与子查询一起使用,但是,BETWEEN 可在子查询内使用。

// 子查询或内部查询或嵌套查询是在另一个 SQLite 查询内嵌入在 WHERE 子句中的查询。
void MainWindow::on_pushButton_40_clicked()
{
    QSqlQuery db_query(db);
    if (db_query.exec("SELECT *FROM student WHERE id IN (SELECT id FROM student WHERE id  > 1) ")){
            QMessageBox::information(NULL,"子查询","子查询成功:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int id = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id = "+QString::number(id) +" name = " +name +" age =  "+QString::number(age));
        }
    }
    else{
          QMessageBox::critical(NULL,"子查询","子查询失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec("UPDATE student SET id = id * 5 WHERE age IN (SELECT age FROM student WHERE age >= 1 )")){
            QMessageBox::information(NULL,"子查询","子查询成功:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int id = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id = "+QString::number(id) +" name = " +name +" age =  "+QString::number(age));
        }
    }
    else{
          QMessageBox::critical(NULL,"子查询","子查询失败:" + db_query.lastError().text(),QMessageBox::Close);
    }

    if (db_query.exec(" DELETE FROM student WHERE age IN (SELECT age FROM student WHERE age > 60 )")){
            QMessageBox::information(NULL,"子查询","子查询成功:"+db_query.lastQuery(),QMessageBox::Close);

            while (db_query.next()) {
            int id = db_query.value(0).toUInt();
            QString name = db_query.value(1).toString();
            int age = db_query.value(2).toUInt();
            ui->textBrowser_4->append(db_query.lastQuery() +";   id = "+QString::number(id) +" name = " +name +" age =  "+QString::number(age));
        }
    }
    else{
          QMessageBox::critical(NULL,"子查询","子查询失败:" + db_query.lastError().text(),QMessageBox::Close);
    }
}

效果

在这里插入图片描述


【26】EXPLAIN (注释)

在 SQLite 语句之前,可以使用 “EXPLAIN” 关键字或 “EXPLAIN QUERY PLAN” 短语,用于描述表的细节。
如果省略了 EXPLAIN 关键字或短语,任何的修改都会引起 SQLite 语句的查询行为,并返回有关 SQLite 语句如何操作的信息。
来自 EXPLAIN 和 EXPLAIN QUERY PLAN 的输出只用于交互式分析和排除故障。
输出格式的细节可能会随着 SQLite 版本的不同而有所变化。
应用程序不应该使用 EXPLAIN 或 EXPLAIN QUERY PLAN,因为其确切的行为是可变的且只有部分会被记录。

// 来自 EXPLAIN 和 EXPLAIN QUERY PLAN 的输出只用于交互式分析和排除故障。
void MainWindow::on_pushButton_41_clicked()
{
        QSqlQuery db_query(db);
        if (db_query.exec("EXPLAIN SELECT *  FROM student  WHERE age >= 1")){
                QMessageBox::information(NULL,"子查询","子查询成功:"+db_query.lastQuery(),QMessageBox::Close);

                while (db_query.next()) {
                QString detail = db_query.value(0).toString(); // 获取查询计划的详细信息
                ui->textBrowser_4->append(db_query.lastQuery() +"; detail =  "+detail);
            }
        }
        else{
              QMessageBox::critical(NULL,"子查询","子查询失败:" + db_query.lastError().text(),QMessageBox::Close);
        }

        ui->textBrowser_4->append("\n");

        if (db_query.exec("EXPLAIN QUERY PLAN SELECT *  FROM student  WHERE age >= 1")){
                QMessageBox::information(NULL,"子查询","子查询成功:"+db_query.lastQuery(),QMessageBox::Close);

                while (db_query.next()) {
                QString detail = db_query.value(0).toString(); // 获取查询计划的详细信息
                ui->textBrowser_4->append(db_query.lastQuery() +"; detail =  "+detail);
            }
        }
        else{
              QMessageBox::critical(NULL,"子查询","子查询失败:" + db_query.lastError().text(),QMessageBox::Close);
        }
}

效果

EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  0
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  1
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  2
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  3
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  4
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  5
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  6
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  7
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  8
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  9
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  10
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  11
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  12
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  13
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  14
EXPLAIN SELECT *  FROM student  WHERE age >= 1; detail =  15


EXPLAIN QUERY PLAN SELECT *  FROM student  WHERE age >= 1; detail =  2

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 教程:从零到大师

首先, 什么是Python? 用python作者Guido van Rossum自己的话来说&#xff0c;Python是这样的一门语言&#xff1a; "它是一门高级编程语言, 它的核心设计理念是让所有代码变得更易阅读&#xff0c;并给开发者们提供一种“仅仅几行代码就能编写编程逻辑”的语法。 那么&am…

SD/StableDiffusion部署图文教程,ai绘画教程,实现谷歌云端零成本部署,中文UI

目录 一、前言 二、准备前提 三、教程说明 四、开始搭建 1、第一步&#xff0c;下载ipynb脚本文件 2、第二步&#xff0c;上传一键脚本文件到谷歌云盘 3、选择该.ipynb文件--右键--打开方式--关联更多应用 4、输入框搜索Colaboratory找到该应用&#xff0c;安装 5、安…

【瑞萨RA6系列】RASC+Keil开发环境搭建和GPIO点灯指南

瑞萨RASCKeil开发环境搭建 一、简单开箱二、资料下载三、芯片简介四、开发环境搭建4.1 安装RASC4.2 安装Keil MDK4.3 安装RA6E1的MDK支持包 五、GPIO点灯指南5.1 创建RASC项目5.2 查阅开发板原理图5.3 设置LED1引脚为输出3.4 编写LED1闪烁的代码5.5 编译Keil项目5.6 修改Keil调…

产品设计.B端设计师不可忽视的产品和用户

B端产品与C端产品不同&#xff0c;前者强调客户价值&#xff0c;企业决策链路长&#xff0c;用户难获得的同时也相对难流失。而作为B端产品设计师&#xff0c;就需要根据B端产品业务特点&#xff0c;从用户、产品等角度进行考量&#xff0c;以求做出符合市场和用户的设计方案。…

【HTTP 协议】

一、HTTP 协议简介 在真实的网络环境中采用 TCP/IP 五层网络传输模型这样的结构传输. 物理层 -> 数据链路层 -> 网络层 -> 传输层 -> 应用层 1. 应用层: 应用层是模型的最顶层&#xff0c;它为用户提供了一种与网络进行通信的方法。应用层包含了各种应用程序&…

【Linux基础及shell脚本】在VMware16中安装CentOS7.6

文章目录 1. Linux和CentOS2. 虚拟机3. 为什么选择在VMware上安装CentOS&#xff1f;4. 准备工作5. 创建新的虚拟机6. 安装CentOS 7.67. 初次启动和设置 在我们了解如何在VMware16中安装CentOS 7.6之前&#xff0c;让我们首先对Linux、CentOS以及虚拟机有一些基本的认识。 1. …

【性能测试一】性能测试概述

目录 &#x1f31f;一、性能测试的基础概念 &#x1f308;1、生活中软件相关的性能问题&#xff1f; &#x1f308;2、性能测试的概念 &#x1f308;3、性能测试与功能测试的区别&#xff1f; &#x1f308;4、什么样的软件属于性能好&#xff1f;什么样的软件属于性能不好…

搭建Vue项目以及项目的常见知识

前言&#xff1a;使用脚手架搭建vue项目&#xff0c;使用脚手架可以开发者能够开箱即用快速地进行应用开发而开发。 搭建 #创建一个基于 webpack 模板的新项目 vue init webpack my-project #选择所需要的选项如图&#xff1a; cd my-project npm run dev访问localhost:808…

分布式数据库架构

分布式数据库架构 1、MySQL常见架构设计 对于mysql架构&#xff0c;一定会使用到读写分离&#xff0c;在此基础上有五种常见架构设计&#xff1a;一主一从或多从、主主复制、级联复制、主主与级联复制结合。 1.1、主从复制 这种架构设计是使用的最多的。在读写分离的基础上…

SpringBoot源码分析(三):SpringBoot的事件分发机制

文章目录 通过源码明晰的几个问题Spring 中的事件Springboot 是怎么做到事件监听的另外两种注册的Listener 源码解析加载listenerSpringApplicationRunListenerEventPublishingRunListenerSimpleApplicationEventMulticaster判断 listener 是否可以接收事件Java 泛型获取 整体流…

【前端|HTML系列第1篇】HTML的基础介绍与初次尝试

大家好&#xff0c;欢迎来到前端入门系列的第一篇博客。在这个系列中&#xff0c;我们将一起学习前端开发的基础知识&#xff0c;从零开始构建网页和Web应用程序。本篇博客将为大家介绍HTML&#xff08;超文本标记语言&#xff09;的基础概念和标签&#xff0c;帮助你快速入门。…

Git进阶系列 | 6. 交互式Rebase

Git是最流行的代码版本控制系统&#xff0c;这一系列文章介绍了一些Git的高阶使用方式&#xff0c;从而帮助我们可以更好的利用Git的能力。本系列一共8篇文章&#xff0c;这是第6篇。原文&#xff1a;Interactive Rebase: Clean up your Commit History[1] 交互式Rebase是Git命…

数据结构:二叉树经典例题(单选题)-->你真的掌握二叉树了吗?(第二弹)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关二叉树的经典例题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

百度开源,一款强大的压测工具,可模拟几十亿并发场景

优点 性能强大统计信息详细使用场景丰富性能 HTTP 每秒新建连接数HTTP 吞吐HTTP 并发连接数UDP TX PPS测试环境配置统计数据开始使用 设置大页编译 DPDK编译 dperf绑定网卡启动 dperf server从客户端发送请求运行测试开源地址 dperf 是一款基于 DPDK 的 100Gbps 网络性能和负载…

小白快速自建博客--halo博客

小白快速自建博客–halo博客 前言&#xff1a;如何快速地搭建属于个人的博客&#xff0c;以下就推荐一个可以个性化的定制属于个人的专属博客–halo博客。 Docker安装 关于docker安装&#xff0c;可以查看文章&#xff1a;Linux下安装docker Docker相关指令 docker相关指令…

网络套接字基本概念

文章目录 1. 认识IP地址2. 认识端口号2.1 理解 "端口号" 和 "进程ID"2.2 理解源端口号和目的端口号 3. 认识TCP协议和UDP协议4. 网络字节序5. sockaddr结构 1. 认识IP地址 IP协议有两个版本&#xff0c;IPv4和IPv6。没有特殊说明的&#xff0c;默认都是指…

第五章 作业(149A)【计算机系统结构】

第五章 作业【计算机系统结构】 前言推荐第五章 作业148 补充910 最后 前言 2023-6-24 10:43:46 以下内容源自《【计算机系统结构】》 仅供学习交流使用 推荐 第三章 作业&#xff08;7BF&#xff09;【计算机系统结构】 答案参考&#xff1a; https://www.docin.com/p-8…

HTML 教程:学习如何构建网页||HTML 简介

HTML 简介 HTML 简介 现在您可以通过如下的一个 HTML 实例来建立一个简单的 HTML 页面&#xff0c;以此来简单了解一下 HTML 的结构。 HTML 实例 <!DOCTYPE html> <html> <head> <title>页面标题(w3cschool.cn)</title> </head> <…

中国电子学会2023年05月份青少年软件编程C++等级考试试卷四级真题(含答案)

1.怪盗基德的滑翔翼 怪盗基德是一个充满传奇色彩的怪盗&#xff0c;专门以珠宝为目标的超级盗窃犯。而他最为突出的地方&#xff0c;就是他每次都能逃脱中村警部的重重围堵&#xff0c;而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼。 有一天&#xff0c;怪盗基德像…

混频器【Multisim】【高频电子线路】

目录 一、实验目的与要求 二、实验仪器 三、实验内容与测试结果 1、测试输入输出波形&#xff0c;说明两者之间的关系 2、测试输出信号的频谱(傅里叶分析法) 3、将其中一个二极管反接&#xff0c;测试输出波形&#xff0c;并解释原因&#xff1b;将两个二极管全部反接&am…