目录
    
   
    QtSql模块层次结构
   
| 层次 | 描述 | 
| 驱动层 | 实现了特定数据库与SQL接口的底层桥接,包括的支持类有QSqlDriver、QSqlDriverCreator<T>、QSqlDriverCreatorBase、QSqlDriverPlugin和QSqlResult | 
| 数据库接口层 | QSqlDatabase类提供了数据库访问类、数据库连接操作,QSqlQuery类提供了与数据库的交互操作,其他支持类还包括QSqlError、QSqlField、QSqlTableModel和QSqlRecord | 
| 用户结构层 | 提供从数据库数据到用于数据表示的窗体的映射,包括的支持类有QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel,这些类均依据Qt的模型/视图结构设计 | 
    QtSql模块提供的数据库驱动插件
   
| 驱 动 | 数据库管理系统 | 
| QDB2 | IBM DB2及其以上版本 | 
| QIBASE | Borland InterBase | 
| QMYSQL | MySQL | 
| QOCI | Oracle Call Interface Driver | 
| QODBC | Open Database Connectivity(ODBC)包括微软SQL Server和其他ODBC兼容数据库 | 
| QPSQL | PostgreSQL版本6.x和7.x | 
| QSQLITE | SQLite版本3及其以上版本 | 
| QSQLITE2 | SQLite版本2 | 
| QTDS | Sybase Adaptive Server | 
    QtSql提供的高层接口
   
| 类 名 | 用 途 | 
| QSqlQueryModel | 基于任意SQL语句的只读模型 | 
| QsqlTableModel | 基于单个表的读写模型 | 
| QSqlRelationalTableModel | QSqlTableModel的子类,增加了外键支持 | 
    小例子
   
    1、创建数据库连接和表
   
 void CreateSqlTable(QSqlDatabase& db, QSqlQuery& query)
{
    //该数据库只在程序运行期间有效,等程序运行结束时就会将其销毁
    db.setDatabaseName(":memory:");
    //db.setHostName("LM123456");                 //设置数据库主机名
    db.setDatabaseName("qtDB.db");              //设置数据库名
    db.setUserName("LiuXiaoMing");              //设置数据库用户名
    db.setPassword("123456");                   //设置数据库密码
    db.open();                             		//打开连接
    qDebug()<< db.isValid();//true
    qDebug()<< db.isOpen(); //true
    //创建数据库表
    //id:变量名;int:类型;primary key:主键
    bool success=query.exec("create table automobil(id int primary key,attribute varchar"
                            ",type varchar,kind varchar,nation int,carnumber int,elevaltor int,distance int,oil int,temperature int)");
    if(success)
        qDebug()<<QObject::tr("数据库表创建成功!\n");
    else
        qDebug()<<QObject::tr("数据库表创建失败!\n");
}
    2、插入数据
   
void InsertInto(QSqlQuery& query)
{
    QTime t;
    t.start();
    //调用prepare()函数指定一个包含占位符的query,然后绑定要插入的值
    query.clear();
    query.prepare("insert into automobil values(?,?,?,?,?,?,?,?,?,?)");
    long records = 10;
    for(int i  =0;i < records; ++i)
    {
        query.bindValue(0,i);//调用bindValue()或addBindValue()函数绑定要插入的值
        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);
        //query.addBindValue(id); 插值单个值
        bool success=query.exec();
        if(!success)
        {
            QSqlError lastError=query.lastError();  //返回语句执行错误原因
            qDebug()<< i << "    "<<lastError.driverText()<<QString(QObject::tr("插入失败"));
        }
    }
    qDebug()<<QObject::tr("插入 %1 条记录,耗时:%2 ms").arg(records).arg(t.elapsed());
#if 0
    //批处理操作
    query.prepare("insert into student values (:id, :name)");
    QVariantList ints;
    ints << 10 << 11 << 12 << 13;
    query.addBindValue(ints);   //插值一列
    QVariantList names;
    // 最后一个是空字符串,应与前面的格式相同
     names << "xiaoming" << "xiaoliang"
                    << "xiaogang" << QVariant(QVariant::String);
    query.addBindValue(names);
    if (!query.execBatch()) //进行批处理,如果出错就输出错误
       qDebug() << query.lastError();
#endif
}
    3、查找数据
   
void SelectData(QSqlQuery& query)
{
/*
    seek(int n) :query指向结果集的第n条记录;
    first() :query指向结果集的第一条记录;
    last() :query指向结果集的最后一条记录;
    next() :query指向下一条记录,每执行一次该函数,便指向相邻的下一条记录;
    previous() :query指向上一条记录,每执行一次该函数,便指向相邻的上一条记录;
    record() :获得现在指向的记录;
    value(int n) :获得属性的值。其中n表示你查询的第n个属性。 获取第几列数据。
    at() :获得现在query指向的记录在结果集中的编号。
   刚执行完query.exec("select *from student");这行代码时,
    query是指向结果集以外的,我们可以利用query.next()使得 query指向结果集的第一条记录。
    当然我们也可以利用seek(0)函数或者first()函数使query指向结果集的第一条记录。
    但是为了节省内存开销,推荐的方法是,在query.exec("select * from student");
    这行代码前加上query.setForwardOnly(true);这条代码,此后只能使用next()和seek()函数。
*/
    query.exec("select * from automobil");  //执行标准Sql语句
    qDebug() << "exec next() :";
    //开始就先执行一次next()函数,那么query指向结果集的第一条记录
    if(query.next())
    {
       //获取query所指向的记录在结果集中的编号
       int rowNum = query.at();
       //获取每条记录中属性(即列)的个数
       int columnNum = query.record().count();
       //获取"name"属性所在列的编号,列从左向右编号,最左边的编号为0
       int fieldNo = query.record().indexOf("id");
       //获取id属性的值,并转换为int型
       int id = query.value(0).toInt();
       //获取name属性的值
       QString name = query.value(fieldNo).toString();
       //将结果输出
       qDebug() << "rowNum is : " << rowNum
                 << " id is : " << id
                 << " name is : " << name
                 << " columnNum is : " << columnNum;
    }
    //定位到结果集中编号为2的记录,即第三条记录,因为第一条记录的编号为0
    qDebug() << "exec seek(2) :";
    if(query.seek(2))
    {
       qDebug() << "rowNum is : " << query.at()
                 << " id is : " << query.value(0).toInt()
                 << " name is : " << query.value(1).toString();
    }
    //定位到结果集中最后一条记录
    qDebug() << "exec last() :";
    if(query.last())
    {
       qDebug() << "rowNum is : " << query.at()
                 << " id is : " << query.value(0).toInt()
                 << " name is : " << query.value(1).toString();
    }
}
    4、更新数据
   
void Update(QSqlQuery& query)
{
    QTime t;
    //更新记录
    t.restart();
    for(int i = 0;i < 10; ++i)
    {
       query.clear();
       query.prepare(QString("update automobil set attribute=?,type=?,"
                             "kind=?,nation=?,"
                             "carnumber=?,elevaltor=?,"
                             "distance=?,oil=?,"
                             "temperature=? where id=%1").arg(i)); // i 对应 %1
       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);
       bool success=query.exec();
       if(!success)
       {
           QSqlError lastError=query.lastError();
           qDebug()<< i << " "<<lastError.driverText()<<QString(QObject::tr("更新失败"));
       }
    }
    qDebug()<<QObject::tr("更新 %1 条记录,耗时:%2 ms").arg(10).arg(t.elapsed());
}
    5、删除数据
   
void Delete(QSqlQuery& query)
{
    QTime t;
    //删除
    t.restart();
    query.exec("delete from automobil where id=15"); //执行删除id为15的记录的操作
    qDebug()<<QObject::tr("删除一条记录,耗时:%1 ms").arg(t.elapsed());
}
    6、主函数
   
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");
    QSqlQuery query;
    CreateSqlTable(db,query);
    InsertInto(query);
    SelectData(query);
    Update(query);
    Delete(query);
    system("pause");
    return 0;
    //return a.exec();
}
    7、*.pro
   
QT += core
QT -= gui
QT += sql
CONFIG += c++11
TARGET = QSQLiteEx
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
        main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
