QT项目开发之数据库基础

    Qt中的QtSql模块提供了对数据库的支持,该模块可以分为三大类别:用户接口层、SQL接口层、驱动层. 其中驱动层是具体数据和SQL接口层之间提供了底层的桥梁;SQL接口层提供了对数据库的访问,其中QSqlDatabase类用来创建链接,QSqlQuery类可以使用SQL语句实现与数据库的交互.


讲在多的理论还不如真刀真抢的来实战,下面我配合代码来讲解QT对数据库的基本操作.

新建空的Qt项目,项目名称databaseDriver,完成后

往项目添加新的main.cpp.connect.h  还需要在databaseDriver.pro文件中添加QT+=sql ,connect.h文件内容如下:


#ifndef CONNECTION_H
#define CONNECTION_H

#include 
#include 
#include 

static bool createConnection()
{
    QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE");
    //db1.setDatabaseName(":memory:");  /* 表明是建立在内存中的数据库 */
    db1.setDatabaseName("my1.db");
    if (!db1.open())
    {
        QMessageBox::critical(0, "Cannot open database",
            "Unable to establish a database connection.", QMessageBox::Cancel);

        return false;
    }
    QSqlQuery query1(db1);
    query1.exec("create table student (id int primary key, "
               "name varchar(20))");
    query1.exec("insert into student values(0, 'LiMing')");
    query1.exec("insert into student values(1, 'LiuTao')");
    query1.exec("insert into student values(2, 'WangHong')");

    QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE");
    db2.setDatabaseName("my2.db");
    if (!db2.open())
    {
        QMessageBox::critical(0, "Cannot open database",
            "Unable to establish a database connection.", QMessageBox::Cancel);

        return false;
    }
    QSqlQuery query2(db2);
    query2.exec("create table student (id int primary key, "
               "name varchar(20))");
    query2.exec("insert into student values(0, 'LiMing')");
    query2.exec("insert into student values(1, 'LiuTao')");
    query2.exec("insert into student values(2, 'WangHong')");
    return true;
}


#endif // CONNECTION_H

部分讲解在注释中已经表明,本文由Linux_Google创建.

这个头文件添加了一个与数据库建立链接的函数,第一行创建了一个SQLite数据库的默认连接,设置数据库名称使用了:memory:表明这个是建立在内存中的数据,my1.db表明是建立在文件中的,db1.open()打开这个数据文件.QSqlQuery创建一个操作数据库的对象,可以传入参数是数据库文件,query1.exec是运行数据库命令的封装函数.


main.cpp文件内容如下

#include 
#include 
#include 
#include 
#include "connection.h"
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
    int numRows;
    QApplication a(argc, argv);

    qDebug() << "Available drivers:";
    QStringList drivers = QSqlDatabase::drivers(); /* 查询所拥有的SQL驱动程序 */
    foreach(QString driver, drivers)
        qDebug() << driver;

    if (!createConnection())
        return 1;

    QSqlDatabase db1 =QSqlDatabase::database("connection1");

    QSqlQuery query1(db1);
    query1.exec("select * from student");

    /* next()下一条记录 previous()上一条记录,first()定位到第一条记录,last()定位到最后一条记录
    seek(n)定位到第n条记录*/
    while(query1.next())
    {
        qDebug() << query1.value(0).toInt() << query1.value(1).toString();
    }

    QSqlDatabase db2 =QSqlDatabase::database("connection1");

    QSqlQuery query2(db2);

    query2.exec("select * from student");

    while(query2.next())
    {
        qDebug() << query2.value(0).toInt() << query2.value(1).toString();
    }

    /* 判断该数据库驱动是否支持QuerySize特性,如果支持,则可以使用size()函数 */
    if(db2.driver()->hasFeature(QSqlDriver::QuerySize))
    {
        qDebug() << "has feauter:query size";
        numRows =query2.size();
    }
    else
    {
        qDebug() << "no feauter:query size";
        query2.last();
        numRows =query2.at()+1;
    }
    qDebug() << "num number:" << numRows;

    query2.seek(1);   /* index is 1,also two line */
    qDebug() << "current index:" << query2.at();

    QSqlRecord record = query2.record();
    int id =record.value("id").toInt();
    QString name = record.value("name").toString();
    qDebug() << "id:" << id << "name:" << name;

    /* 获取索引为1的字段,即第二个字段,name */
    QSqlField field = record.field(1);
    /* 输出字段名和字段值 */
    qDebug() << "second field:" << field.name() << "field value:" << field.value();

    /* 下面两种情况是等价的 */
    #if 1
       query2.exec("insert into student (id, name) values (520, 'Linux_Google')");
    #else  /* 名称绑定 */
        query2.prepare("inset into student (id,name) values(:id,:name)");
        int idValue = 520;
        QString nameValue = "Linux_Google";
        query2.bindValue(":id",idValue);
        query2.bindValue(":name",nameValue);
        query2.exec();
        //query2.prepare("insert into student (id, name) values (?, ?)");
        /* 或者可以用下面几条语句替换,这个是位置绑定 */
        //    int idValue = 520;
        //    QString nameValue = "Linux_Google";
        //    query2.addBindValue(idValue);
        //    query2.addBindValue(nameValue);
        //    query2.exec();

    #endif
    query2.prepare("insert into student (id, name) values (?, ?)");

    QVariantList ids;
    ids << 20 << 21 << 22;
    query2.addBindValue(ids);
    QVariantList names;
    names << "xiaoming" << "xiaoliang" << "xiaogang";
    query2.addBindValue(names);
    if(!query2.execBatch()) qDebug() << query2.lastError();

    query2.exec("update student set name = 'xiaohong' where id = 20");

    query2.exec("delete from student where id = 21");
    query2.exec("delete from student where name = ChenYun");



    query2.exec("select * from student");

    while(query2.next())
    {
        qDebug() << query2.value(0).toInt() << query2.value(1).toString();
    }

    return a.exec();
}



QSqlDatabase::drivers()获取本机上可用的数据库驱动列表,foreach遍历输出.用createConnection建立了一个连接,然后创建了两个数据库操作对象query1,query2分别指向db1,db2.query1.next()作用是输出遍历到的库文件,输出一行后自动将索引值加1.query2.size()是来判断数据库文件的行数的,前提是看看是否支持这个函数,程序中有判断.


程序中有四种方法插入数据库文件,

直接插入

query2.exec("insert into student (id, name) values (520, 'Linux_Google')");

名称绑定插入法

query2.prepare("inset into student (id,name) values(:id,:name)");
        int idValue = 520;
        QString nameValue = "Linux_Google";
        query2.bindValue(":id",idValue);
        query2.bindValue(":name",nameValue);
        query2.exec();

位置绑定插入法:

        //query2.prepare("insert into student (id, name) values (?, ?)");

        //    int idValue = 520;
        //    QString nameValue = "Linux_Google";
        //    query2.addBindValue(idValue);
        //    query2.addBindValue(nameValue);
        //    query2.exec();

多项同时插入法:

query2.prepare("insert into student (id, name) values (?, ?)");

    QVariantList ids;
    ids << 20 << 21 << 22;
    query2.addBindValue(ids);
    QVariantList names;
    names << "xiaoming" << "xiaoliang" << "xiaogang";
    query2.addBindValue(names);
    if(!query2.execBatch()) qDebug() << query2.lastError();

query2.execBatch()是用来判断插入出错操作,剩下的就是操作数据库文件的一些指令,比较简单.


代码中用到了一个库函数QVariant,QVariant是一种可以存储不同类型的数据结构,比QStringList更加强大.


最后一个知识点在代码中没有体现,那就是事务.用我们Linux内核的解释就是竞争冒险,原子变量操作.事务操作可以保证一个事务操作的原子性,就是对一个数据的操作序列,它会把数据库操作看成一个不可分割的工作单位.如果底层数据库支持事务的话,那么QSqlDatabase::database().transaction();来启动一个事务,QSqlDatabase::database().commit();
或QSqlDatabase::database().rollback();   结束这个事务,当使用事务时必须在创建查询以前就开始事务,也就是说我们操作数据库用事务就需要在启动和停止之间.              


                                                                                                                         文章出自:Linux_Google

你可能感兴趣的:(QT)