Qt5操作SQLite数据库实例

本文介绍如何使用Qt操作SQLite数据库,包括创建数据库、表结构定义、增删改查操作及性能展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt操作SQLite数据库

Qt提供了一种进程内数据库SQLite。它小巧灵活,无须额外安装配置且支持大部分ANSI SQL92标准,是一个轻量级的数据库,概括起来具有以下优点。

  • (1)SQLite的设计目的是实现嵌入式SQL数据库引擎,它基于纯C语言代码,已经应用在非常广泛的领域内。
  • (2)SQLite在需要持久存储时可以直接读写硬盘上的数据文件,在无须持久存储时也可以将整个数据库置于内存中,两者均不需要额外的服务器端进程,即SQLite是无须独立运行的数据库引擎。
  • (3)开放源代码,整套代码少于3万行,有良好的注释和90%以上的测试覆盖率。
  • (4)少于250KB的内存占用容量(gcc编译情况下)。
  • (5)支持视图、触发器和事务,支持嵌套SQL功能。
  • (6)提供虚拟机用于处理SQL语句。
  • (7)不需要配置,不需要安装,也不需要管理员。
  • (8)支持大部分ANSI SQL92标准。
  • (9)大部分应用的速度比目前常见的客户端/服务器结构的数据库快。
  • (10)编程接口简单易用。

 操作数据库实例

基于控制台的程序,使用SQLite数据库完成大批量数据的增加、删除、更新和查询操作并输出。

操作步骤如下。

(1)在“QSQLiteEx.pro”文件中添加如下代码:    

 QT += sql

(2)源文件“main.cpp”的具体代码。

#include <QCoreApplication>
#include<QSqlDatabase>
#include<QSqlError>
#include<QSqlQuery>
#include<QSqlDriver>
#include<QSqlRecord>
#include<QTextCodec>
#include<QDebug>
#include<QTime>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTextCodec::setCodecForLocale (QTextCodec::codecForLocale ());//设置中文显示
    //以QSQLITE为数据库类型,在本进程地址空间内创建一个SQLite数据库,
    QSqlDatabase db = QSqlDatabase::addDatabase ("QSQLITE");
    db.setHostName ("easybook-3313b0");//设置数据库主机名
    db.setDatabaseName ("qtDB.db");//设置数据库主机名
    db.setUserName ("Luo");//设置数据库用户名
    db.setPassword ("123456");//设置数据库密码
    db.open ();//打开连接
    //创建数据库表
    QSqlQuery query;
    bool success = query.exec ("create table automobile"
                               "(id int primary key,"//设置id为主关键字
                               "attribute varchar,"
                               "type varchar,"
                               "kind varchar,"
                               "nation int,"
                               "carnumber int,"
                               "elevaltor int,"
                               "distance int,"
                               "oil int,"
                               "temperature int)"
                               );

    if(success)
        qDebug() << "数据库表创建成功!";
    else
        qDebug() << "创建失败";
    //查询
    query.exec ("select * from automobile");
    QSqlRecord rec = query.record ();
    qDebug() << "automobile表字段数:"<<rec.count ();
    //插入记录
    QTime t;
    t.start();//启动一个计时器,统计操作时间
    query.prepare ("insert into automobile values(?,?,?,?,?,?,?,?,?,?)");
    long records = 100;
    //向表中任意插入100条记录
    for(int i=0; i<records; i++)
    {
        query.bindValue (0,i);
        query.bindValue (1,"四轮");
        query.bindValue (2,"轿车");
        query.bindValue (3,"富康");
        query.bindValue (4,rand ()%100);
        query.bindValue (5,rand ()%10000);
        query.bindValue (6,rand ()%300);
        query.bindValue (7,rand ()%200000);
        query.bindValue (8,rand ()%52);
        query.bindValue (9,rand ()%100);
        success = query.exec ();
        if(!success)
        {
            QSqlError lastError = query.lastError ();
            qDebug() << lastError.driverText ()<<"插入失败";
        }
    }
    qDebug() << QString("插入 %1 条记录,耗时:%2ms").arg (records).arg (t.elapsed ());
    //排序
    t.restart ();//重启计时器
    success = query.exec ("select * from automobile order by id desc");
    if(success)
        qDebug() << QString("排序 %1 条记录,耗时:%2 ms").arg (records).arg (t.elapsed ());
    else
        qDebug() << "排序失败";
    //更新记录
    t.restart ();
    for(int i=0; i<records; i++)
    {
        query.clear ();
        query.prepare (QString("update automobile set attribute=?,"
                               "type=?,"
                               "kind=?,"
                               "nation=?"
                               "carnumber=?,elevaltor=?,"
                               "distance=?,oil=?,"
                               "temperature=? where id=%1").arg (i));
        query.bindValue (0,"四轮");
        query.bindValue (1,"轿车");
        query.bindValue (2,"富康");
        query.bindValue (3,rand ()%100);
        query.bindValue (4,rand ()%10000);
        query.bindValue (5,rand ()%300);
        query.bindValue (6,rand ()%200000);
        query.bindValue (7,rand ()%52);
        query.bindValue (8,rand ()%100);
        success = query.exec ();
        if(!success)
        {
            QSqlError lastError = query.lastError ();
            qDebug() << lastError.driverText ()<<QString("更新失败");
        }
    }
    qDebug() << QString("更新 %1 条记录,耗时:%2 ms").arg (records).arg (t.elapsed ());
    //删除
    t.restart ();
    query.exec ("delete from automobile where id=15");
    qDebug() << QString("删除一条记录,耗时:%1 ms").arg (t.elapsed ());

    return 0;
    //return a.exec();
}

注意:上述代码执行一遍后会在具体的编译文件夹中生成qtDB.db文件,里面有一个automobile的表格,如果再执行一遍上述代码,会提示数据库表创建失败,更改表格的名字重新创建一个即可。

其中,

(a) QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE"):以“QSQLITE”为数据库类型,在本进程地址空间内创建一个SQLite数据库。此处涉及的知识点有以下两点。

① 在进行数据库操作之前,必须首先建立与数据库的连接。数据库连接由任意字符串标识。在没有指定连接的情况下,QSqlDatabase可以提供默认连接供Qt其他的SQL类使用。

其中,静态函数QSqlDatabase::addDatabase()返回一条新建立的数据库连接,其原型为:

QSqlDatabase::addDatabase
(
     const QString &type,
     const QString &connectionName=QLatin1String(defaultConnection)
)

 参数type为驱动名,本例使用的是QSQLITE 驱动。  参数connectionName为连接名,默认值为默认连接,本例的连接名为connect。如果没有指定此参数,则新建立的数据库连接将成为本程序的默认连接,并且可以被后续不带参数的函数database()引用。如果指定了此参数(连接名),则函数database(connectionName)将获取这个指定的数据库连接。

② QtSql模块使用驱动插件(driver plugins)与不同的数据库接口通信。由于QtSql模块的应用程序接口是与具体数据库无关的,所以所有与数据库相关的代码均包含在这些驱动插件中。目前,Qt支持的数据库驱动插件见表

驱    动

数据库管理系统

QDB2

IBM DB2及其以上版本

QIBASE

Borland InterBase

QMYSQL

MySQL

QOCI

Oracle Call Interface Driver

QODBC

Open Database Connectivity(ODBC)包括Microsoft SQL Server和其他ODBC兼容数据库

QPSQL

PostgreSQL版本6.x和7.x

QSQLITE

SQLite版本3及其以上版本

QSQLITE2

SQLite版本2

QTDS

Sybase Adaptive Server

(b) db.setDatabaseName("qtDB.db"):以上创建的数据库以“qtDB.db”为数据库名。它是SQLite在建立内存数据库时唯一可用的名字。

(c) QSqlQuery query:创建QSqlQuery对象。QtSql模块中的QSqlQuery类提供了一个执行SQL语句的接口,并且可以遍历执行的返回结果集。除QSqlQuery类外,Qt还提供了三种用于访问数据库的高层类,即QSqlQueryModel、QSqlTableModel和QSqlRelationTableModel。它们无须使用SQL语句就可以进行数据库操作,而且可以很容易地将结果在表格中表示出来。访问数据库的高层类见表

类    名

用    途

QSqlQueryModel

基于任意SQL语句的只读模型

QsqlTableModel

基于单个表的读写模型

QSqlRelationalTableModel

QSqlTableModel的子类,增加了外键支持

 (d) bool success=query.exec("create table automobile…"):创建数据库表“automobile”,该表具有10个字段。在执行exec()函数调用后,就可以操作返回的结果了。

(e) query.prepare("insert into automobil values(?,?,?,?,?,?,?,?,?,?)"):如果要插入多条记录,或者避免将值转换为字符串(即正确地转义),则可以首先调用prepare()函数指定一个包含占位符的query,然后绑定要插入的值。Qt对所有数据库均可以支持Qracle类型的占位符和ODBC类型的占位符。此处使用了ODBC类型的定位占位符。

等价于使用Oracle语法的有名占位符的具体形式如下:

query.prepare("insert into automobile(id,attribute,type,kind,nation,
    carnumber,elevaltor,distance,oil,temperature) 
    values(:id, :attribute, :type, :kind, :nation,
    :carnumber,:elevaltor,:distance,:oil,:temperature)");
    long records=100;
    for(int i=0;i<records;i++)
    {
        query.bindValue(:id,i);
        query.bindValue(:attribute,"四轮");
        query.bindValue(:type,"轿车");
        query.bindValue(:kind,"富康");
        query.bindValue(:nation,rand()%100);
        query.bindValue(:carnumber,rand()%10000);
        query.bindValue(:elevaltor,rand()%300);
        query.bindValue(:distance,rand()%200000);
        query.bindValue(:oil,rand()%52);
        query.bindValue(:temperature,rand()%100);
	}

(f) query.bindValue(0,i):调用bindValue()或addBindValue()函数绑定要插入的值。

(g) success=query.exec():调用exec()函数在query中插入对应的值,之后,可以继续调用bindValue()或addBindValue()函数绑定新值,然后再次调用exec()函数在query中插入新值。

(h) qDebug()<<QObject::tr("插入 %1 条记录,耗时:%2 ms").arg(records).arg (t.elapsed()):向表中插入任意的100条记录,操作成功后输出操作消耗的时间。

(i) success=query.exec("select * from automobile order by id desc"):按id字段的降序将查询表中刚刚插入的100条记录进行排序。

(j) query.prepare(QString("update automobile set…")):更新操作与插入操作类似,只是使用的SQL语句不同。

(k) query.exec("delete from automobile where id=15"):执行删除id为15的记录的操作。

执行结果:

automobile表字段数: 10
"插入 100 条记录,耗时:16607ms"
"排序 100 条记录,耗时:1 ms"
"更新 100 条记录,耗时:18269 ms"
"删除一条记录,耗时:0 ms"

实例2: 

#include <QCoreApplication>
#include<QSqlDatabase>
#include<QSqlError>
#include<QSqlQuery>
#include<QSqlDriver>
#include<QSqlRecord>
#include<QTextCodec>
#include<QDebug>
#include<QTime>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTextCodec::setCodecForLocale (QTextCodec::codecForLocale ());//设置中文显示
    //以QSQLITE为数据库类型,在本进程地址空间内创建一个SQLite数据库,
    QSqlDatabase db = QSqlDatabase::addDatabase ("QSQLITE");
    db.setHostName ("easybook-3313b0");//设置数据库主机名
    db.setDatabaseName ("qtDB.db");//设置数据库主机名
    db.setUserName ("Luo");//设置数据库用户名
    db.setPassword ("123456");//设置数据库密码
    db.open ();//打开连接
    //创建数据库表
    QSqlQuery query;
    bool success;
    //查询
   success =  query.exec ("select * from automobile");
   if(success)
       qDebug() << "查询成功!";
   else
       qDebug() << "查询失败";
   // record()返回的是当前query的字段信息,也就是表头,
   //如果query指向一个有效行,将返回那一行的数据
   QSqlRecord rec = query.record ();
   //打印表头
   qDebug() << "打印表头:";
   int index=0;
   QStringList fieldList;
   while(!rec.fieldName (index).isEmpty ())
   {
       fieldList << rec.fieldName (index++);
   }
   qDebug() << fieldList;

   qDebug() << "automobile表字段数(列数):"<<rec.count ();
   //返回指定字段的下标
   int idIndex = rec.indexOf ("id");
   qDebug() << "idIndex:"<<idIndex;

   /* bool QSqlQuery::next()
    * 将query指向查询结果的下一个
    * 规则:
    * 1,如果当前query就是最后一条记录,将不改变query,直接返回false
    * 2,正常情况:将查询结果指向下一个,返回true
    */

   query.next();
   query.next();//将指向第2行数据
   QVariant value = query.value (idIndex);
   qDebug() << "第二行id:" <<value.toString ();
   //打印其余id
   while (query.next())
        qDebug() << query.value(idIndex).toString(); // output all names
   //使用的是 INSERT INTO tableName VALUES(...) 格式,注意字符串要打单引号‘’
   success =  query.exec ("insert into automobile values("
                          "666,'三轮','bycycle','Benz',8,8848999,123,987654321,"
                          "100,6"
                          ")");
   if(success)
       qDebug() << "插入成功!";
   else
       qDebug() << "插入失败";
    return 0;
    
}
查询成功!
打印表头:
("id", "attribute", "type", "kind", "nation", "carnumber", "elevaltor", "distance", "oil", "temperature")
automobile表字段数(列数): 10
idIndex: 0
第二行id: "1"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值