界面编程之QT的数据库操作20180801

/*******************************************************************************************/一、数据库连接Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作。这里我们所说的“平台独立”,既包括操作系统平台,有包括各个数据库平台。另外,我们强调了“基于 SQL”,因为 NoSQL 数据库至今没有一个通用查询方法,所以不可能提供一种通用的 NoSQL 数据库的操作。Qt 的数据库操作还可以很方便的与 model/view 架构进行整合。通常来说,我们对数据库的操作更多地在于对数据库表的操作,而这正是 model/view 架构的长项。 Qt 使用QSqlDatabase表示一个数据库连接。更底层上,Qt 使用驱动(drivers)来与不同的数据库 API 进行交互。Qt 桌面版本提供了如下几种驱动:驱动         数据库QDB2       IBM DB2 (7.1 或更新版本)QIBASE    Borland InterBaseQMYSQL  MySQLQOCI        Oracle Call Interface DriverQODBC    Open Database Connectivity (ODBC) – Microsoft SQL Server 及其它兼容 ODBC 的数据库QPSQL     PostgreSQL (7.3 或更新版本)QSQLITE2        SQLite 2QSQLITE  SQLite 3QSYMSQL        针对 Symbian 平台的SQLite 3QTDS        Sybase Adaptive Server (自 Qt 4.7 起废除)不过,由于受到协议的限制,Qt 开源版本并没有提供上面所有驱动的二进制版本,而仅仅以源代码的形式提供。通常,Qt 只默认搭载 QSqlite 驱动(这个驱动实际还包括 Sqlite 数据库,也就是说,如果需要使用 Sqlite 的话,只需要该驱动即可)。我们可以选择把这些驱动作为 Qt 的一部分进行编译,也可以当作插件编译。 如果习惯于使用 SQL 语句,我们可以选择QSqlQuery类;如果只需要使用高层次的数据库接口(不关心 SQL 语法),我们可以选择使用QsqlTableModel类。在使用时,我们可以通过QSqlDatabase::drivers();找到系统中所有可用的数据库驱动的名字列表。我们只能使用出现在列表中的驱动。 1.操作数据库的依赖使用数据库的时候,需要加入数据库的库文件,比如mysql:如果没有在项目中加入mysql的库(需要自己去下载然后添加,比如window的libmysql.dll),就会提示驱动没有加载的错误数据库库文件(libmysql.dll)需要放到qt的安装目录里面的bin目录下 2.项目配置文件的修改使用数据库时,需要在项目文件中加上:QT += sql 3.数据库连接代码#include      //打印Qt支持的数据库驱动    qDebug() << QSqlDatabase::drivers(); 可以得知,qt支持的数据库:sqllite 静态数据库,不需要服务器,类似文件那样,保存的是.db的文件,但是操作是数据的操作方式     开源,提供.h .c文件,文件型数据库mysqlobdc windows提供好的一个数据库操作库,封装好,不需要sql语句都可以操作psql 现在用mysql举例:     //添加MySql数据库    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");     //连接数据库    db.setHostName("127.0.0.1"); //数据库服务器IP 端口默认是3236,不需要设置    db.setUserName("root"); //数据库用户名    db.setPassword("123456"); //密码    db.setDatabaseName("info"); //使用哪个数据库,mysql中创建的数据库    //打开数据库    if( !db.open() ) //数据库打开失败    {//如果没有在项目中加入mysql的库(需要自己去下载然后添加,比如window的libmysql.dll),就会提示驱动没有加载的错误        QMessageBox::warning(this, "错误", db.lastError().text());//此时需要,数据库库文件(libmysql.dll)需要放到qt的安装目录里面的bin目录下        return;    } /*******************************************************************************************/二、数据库插入 #include //执行sql语句需要的头文件     QSqlQuery query;//只操作一个数据库时不需要传入数据库对象    query.exec("create table student(id int primary key, name varchar(255), age int, score int);");    //这样创建对象后,传入sql语句就可以操作了        1.当需要操作多个数据库(Database)时,有两点需要注意:1).创建数据库对象时,需要传入标识,用来区分创建出来的数据库和其他的不同QSqlDatabase db1 = QSqlDatabase::addDatabase("QMYSQL", "a");2).操作数据时,需要传入数据库对象,来指明是哪个数据库。同时如果前面创建给了标识,则这里创建查询对象时必须传入数据库对象,否则操作将不成功QSqlQuery query1(db1);query1.exec("create table student(id int primary key, name varchar(255), age int, score int);");        2.插入    QSqlQuery query;    query.exec("insert into student(id, name, age, score) values(1, 'mike', 18, 59);");3.批量插入,有两种方式:1).odbc(windows)风格  预处理语句  ? 相当于 占位符    query.prepare("insert into student(name, age, score) values(?, ?, ?)");    给字段设置内容 通过list,list可以放任何类型    QVariantList nameList;    nameList << "xiaoming" << "xiaolong" << "xiaojiang";    QVariantList ageList;    ageList << 11 << 22 << 33;    QVariantList scoreList;    scoreList << 59 << 69 << 79;  给字段绑定相应的值 按顺序绑定,否则插入不成功    query.addBindValue(nameList);    query.addBindValue(ageList);    query.addBindValue(scoreList);  执行预处理命令    query.execBatch();        2).oracle风格  预处理语句  占位符 : + 自定义名字    query.prepare("insert into student(name, age, score) values(:name, :age, :score)");  给字段设置内容 list    QVariantList nameList;    nameList << "xiaoa" << "xiaob" << "xiaoc";    QVariantList ageList;    ageList << 33 << 44 << 55;    QVariantList scoreList;    scoreList << 89 << 90 << 99;  给字段绑定,有标识符指定了,所以不局限于顺序    query.bindValue(":name", nameList);    query.bindValue(":score", scoreList);    query.bindValue(":age", ageList);   执行预处理命令    query.execBatch(); /*******************************************************************************************/三、数据库删除和遍历1.删除    //开启一个事务,    QSqlDatabase::database().transaction();//QSqlDatabase::database()获取数据库然后调用开启事务函数     //确定删除    QSqlDatabase::database().commit();          //回滚,撤销         QSqlDatabase::database().rollback();          2.遍历(查找所有):   查询返回结果不包括字段,从第一行记录开始,即第0个为第一条记录            QSqlQuery query;    query.exec("select * from student");//如果只是查一行,sql中加上where条件过滤即可     while(query.next()) //一行一行遍历,执行完自动跳到下一行,从第一行记录开始    {        //取出当前行的内容,取的时候以列为单位,第0列即第一列id,除了用下标来取之外还可以用字段名来取值        qDebug() << query.value(0).toInt()                 << query.value(1).toString()                 << query.value("age").toInt()                 << query.value("score").toInt();    }                上述代码具体见《Database》
 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private slots:
19     void on_buttonDel_clicked();
20 
21     void on_buttonSure_clicked();
22 
23     void on_buttonCancel_clicked();
24 
25 private:
26     Ui::Widget *ui;
27 };
28 
29 #endif // WIDGET_H
widget.hwidget.cpp /*******************************************************************************************/四、sqlite    //添加Sqlite数据库    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");    //设置数据库 后面都一样,注意,自动累加auto_increment,sqlite不支持。 上述代码具体见《SqlLite》
 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 };
21 
22 #endif // WIDGET_H
widget.h
 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include <QSqlDatabase>
 4 #include <QDebug>
 5 #include <QMessageBox>
 6 #include <QSqlError>
 7 #include <QSqlQuery>
 8 #include <QVariantList>
 9 
10 Widget::Widget(QWidget *parent) :
11     QWidget(parent),
12     ui(new Ui::Widget)
13 {
14     ui->setupUi(this);
15 
16     //打印Qt支持的数据库驱动
17     qDebug() << QSqlDatabase::drivers();
18 
19     //添加Sqlite数据库
20     QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
21     //设置数据库
22     db.setDatabaseName("../info.db");
23 
24     //打开数据库
25     if( !db.open() ) //数据库打开失败
26     {
27         QMessageBox::warning(this, "错误", db.lastError().text());
28         return;
29     }
30 
31     QSqlQuery query;
32     query.exec("create table student(id int primary key, name varchar(255), age int, score int);");
33 
34     query.prepare("insert into student(name, age, score) values(?, ?, ?)");
35     //给字段设置内容 list
36     QVariantList nameList;
37     nameList << "xiaoming" << "xiaolong" << "xiaojiang";
38     QVariantList ageList;
39     ageList << 11 << 22 << 33;
40     QVariantList scoreList;
41     scoreList << 59 << 69 << 79;
42     //给字段绑定相应的值 按顺序绑定
43     query.addBindValue(nameList);
44     query.addBindValue(ageList);
45     query.addBindValue(scoreList);
46     //执行预处理命令
47     query.execBatch();
48 
49     query.exec("select * from student");
50 
51     while(query.next()) //一行一行遍历
52     {
53         //取出当前行的内容
54         qDebug() << query.value(0).toInt()
55                  << query.value(1).toString()
56                  << query.value("age").toInt()
57                  << query.value("score").toInt();
58     }
59 
60 
61 
62 }
63 
64 Widget::~Widget()
65 {
66     delete ui;
67 }
widget.cpp /*******************************************************************************************/五、可视化操作数据库Qt 不仅提供了这种使用 SQL 语句的方式,还提供了一种基于模型的更高级的处理方式。这种基于QSqlTableModel 的模型处理更为高级,如果对 SQL 语句不熟悉,并且不需要很多复杂的查询,这种QSqlTableModel模型基本可以满足一般的需求。即使用可以不懂sql语句都可以操作的类,来操作数据库 model/view 架构:ModelView 模型视图Model 单独一个类,只做一件事情,存储数据view  单独一个类,只做一件事情,显示和修改数据 使用ui中的Item Views中的Table View 1.使用模型操作数据库#include //表格的模型     //设置模型    model = new QSqlTableModel(this);    model->setTable("student");//自动和数据库关联上了,但是还需要指定使用哪个表     //把model放在view,如果没有放进去,则model只是可以操作数据并不会显示出来    ui->tableView->setModel(model);//但是此时里面还没有数据,需要model来显示数据     //显示model里的数据    model->select();//这样就把表中所有的数据显示成表格的样子在窗口中          //此时修改窗口中表格的数据,数据库里面的内容也会随之改动                 另外需要注意,由于QSqlTableModel只是一种高级操作,肯定没有实际 SQL 语句方便。         具体来说,我们使用QSqlTableModel只能进行 SELECT * 的查询,不能只查询其中某些列的数据。        设置model一些属性:          修改字段的显示效果  model->setHeaderData(0, Qt::Horizontal, "学号");//水平方向第0列即id显示为汉字学号   model->setEditStrategy(QSqlTableModel::OnManualSubmit); 设置view中的数据库不允许修改,只是显示数据里面的内容。//表现为双击不会让用户修改的现象    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);   2.可视化增加一条记录:    //添加空记录    QSqlRecord record = model->record(); //获取空记录,传入标号后就是获取某一行    //获取行号    int row = model->rowCount();    model->insertRecord(row, record);//在指定行插入空记录,这是界面上就会出现一个空行,                                                                               //用户就可以在空行里面填入输入,填入好后就实现了增加记录 3.可视化提交:    model->submitAll(); //提交动作 4.可视化回滚:    model->revertAll(); //取消所有动作    model->submitAll(); //提交动作,//取消也是动作,要生效还得提交一次 5.可视化删除,注意可以选中多行删除(需要用到模型的概念:选中的多行就形成一个模型):    //获取选中的模型    QItemSelectionModel *sModel =ui->tableView->selectionModel();    //取出模型中的索引(每条记录的索引集合)    QModelIndexList list = sModel->selectedRows();    //删除所有选中的行    for(int i = 0; i < list.size(); i++)    {        model->removeRow( list.at(i).row() );//传入记录的行号    } 6.可视化查找(以通过名字查找举例):    QString name = ui->lineEdit->text();    QString str = QString("name = '%1'").arg(name);//过滤条件格式,注意字符串不能少了单引号     model->setFilter(str);//设定过滤条件    model->select();//过滤完后显示一下 上述代码具体见《ModelView》
 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 #include <QSqlTableModel>
 6 
 7 namespace Ui {
 8 class Widget;
 9 }
10 
11 class Widget : public QWidget
12 {
13     Q_OBJECT
14 
15 public:
16     explicit Widget(QWidget *parent = 0);
17     ~Widget();
18 
19 private slots:
20     void on_buttonAdd_clicked();
21 
22     void on_buttonSure_clicked();
23 
24     void on_buttonCancel_clicked();
25 
26     void on_buttonDel_clicked();
27 
28     void on_buttonFind_clicked();
29 
30 private:
31     Ui::Widget *ui;
32     QSqlTableModel *model;
33 };
34 
35 #endif // WIDGET_H
widget.hwidget.cpp 

相关内容推荐