界面编程之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 InterBase

QMYSQL  MySQL

QOCI        Oracle Call Interface Driver

QODBC    Open Database Connectivity (ODBC) – Microsoft SQL Server 及其它兼容 ODBC 的数据库

QPSQL     PostgreSQL (7.3 或更新版本)

QSQLITE2        SQLite 2

QSQLITE  SQLite 3

QSYMSQL        针对 Symbian 平台的SQLite 3

QTDS        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 <QSqlDatabase>

    //打印Qt支持的数据库驱动

    qDebug() << QSqlDatabase::drivers();

可以得知,qt支持的数据库:

sqllite 静态数据库,不需要服务器,类似文件那样,保存的是.db的文件,但是操作是数据的操作方式

     开源,提供.h .c文件,文件型数据库

mysql

obdc 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 <QSqlQuery>//执行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.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     //添加MySql数据库
 20     QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
 21 
 22     //连接数据库
 23     db.setHostName("127.0.0.1"); //数据库服务器IP
 24     db.setUserName("root"); //数据库用户名
 25     db.setPassword("123456"); //密码
 26     db.setDatabaseName("info"); //使用哪个数据库
 27 
 28 
 29     //打开数据库
 30     if( !db.open() ) //数据库打开失败
 31     {
 32         QMessageBox::warning(this, "错误", db.lastError().text());
 33         return;
 34     }
 35 
 36 //    QSqlQuery query;
 37 //    query.exec("create table student(id int primary key, name varchar(255), age int, score int);");
 38 
 39 
 40 /*
 41      QSqlDatabase db1 = QSqlDatabase::addDatabase("QMYSQL", "a");
 42      db1.setHostName("127.0.0.1"); //数据库服务器IP
 43      db1.setUserName("root"); //数据库用户名
 44      db1.setPassword("123456"); //密码
 45      db1.setDatabaseName("test"); //使用哪个数据库
 46 
 47      //打开数据库
 48      if( !db1.open() ) //数据库打开失败
 49      {
 50          QMessageBox::warning(this, "错误", db.lastError().text());
 51          return;
 52      }
 53 
 54      QSqlQuery query1;
 55      query1.exec("create table student(id int primary key, name varchar(255), age int, score int);");
 56 */
 57 
 58     //插入
 59     //QSqlQuery query;
 60 //    query.exec("insert into student(id, name, age, score) values(1, 'mike', 18, 59);");
 61 
 62     //批量插入
 63     //odbc风格
 64     //预处理语句
 65     // ? 相当于 占位符
 66 //    query.prepare("insert into student(name, age, score) values(?, ?, ?)");
 67 //    //给字段设置内容 list
 68 //    QVariantList nameList;
 69 //    nameList << "xiaoming" << "xiaolong" << "xiaojiang";
 70 //    QVariantList ageList;
 71 //    ageList << 11 << 22 << 33;
 72 //    QVariantList scoreList;
 73 //    scoreList << 59 << 69 << 79;
 74 //    //给字段绑定相应的值 按顺序绑定
 75 //    query.addBindValue(nameList);
 76 //    query.addBindValue(ageList);
 77 //    query.addBindValue(scoreList);
 78 //    //执行预处理命令
 79 //    query.execBatch();
 80 
 81     //oracle风格
 82     //占位符 : + 自定义名字
 83 //    query.prepare("insert into student(name, age, score) values(:name, :age, :score)");
 84 //    //给字段设置内容 list
 85 //    QVariantList nameList;
 86 //    nameList << "xiaoa" << "xiaob" << "xiaoc";
 87 //    QVariantList ageList;
 88 //    ageList << 33 << 44 << 55;
 89 //    QVariantList scoreList;
 90 //    scoreList << 89 << 90 << 99;
 91 //    //给字段绑定
 92 //    query.bindValue(":name", nameList);
 93 //    query.bindValue(":score", scoreList);
 94 //    query.bindValue(":age", ageList);
 95 
 96 //    //执行预处理命令
 97 //    query.execBatch();
 98 
 99     QSqlQuery query;
100     query.exec("select * from student");
101 
102     while(query.next()) //一行一行遍历
103     {
104         //取出当前行的内容
105         qDebug() << query.value(0).toInt()
106                  << query.value(1).toString()
107                  << query.value("age").toInt()
108                  << query.value("score").toInt();
109     }
110 
111 
112 }
113 
114 Widget::~Widget()
115 {
116     delete ui;
117 }
118 
119 void Widget::on_buttonDel_clicked()
120 {
121     //获取行编辑内容
122     QString name = ui->lineEdit->text();
123 
124 
125     QString sql = QString("delete from student where name = '%1'").arg(name);
126 
127     //开启一个事务
128     QSqlDatabase::database().transaction();
129     QSqlQuery query;
130     query.exec(sql);
131 
132 }
133 
134 void Widget::on_buttonSure_clicked()
135 {
136     //确定删除
137     QSqlDatabase::database().commit();
138 }
139 
140 void Widget::on_buttonCancel_clicked()
141 {
142     //回滚,撤销
143      QSqlDatabase::database().rollback();
144 }
widget.cpp

/*******************************************************************************************/

四、sqlite

sqlite是本地数据库,不需要链接

    //添加Sqlite数据库

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

    //设置数据库

    db.setDatabaseName("../info.db");//注意整个.db文件可以自己新建一个文本文件然后重命名即可

后面都一样,注意,自动累加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 <QSqlTableModel>//表格的模型

    //设置模型

    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的编辑模式,手动提交修改,修改后需要确定后才会修改到数据库

  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.h
  1 #include "widget.h"
  2 #include "ui_widget.h"
  3 #include <QSqlDatabase>
  4 #include <QDebug>
  5 #include <QMessageBox>
  6 #include <QSqlError>
  7 #include <QSqlTableModel>
  8 #include <QSqlRecord>
  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     //添加MySql数据库
 20     QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
 21 
 22     //连接数据库
 23     db.setHostName("127.0.0.1"); //数据库服务器IP
 24     db.setUserName("root"); //数据库用户名
 25     db.setPassword("123456"); //密码
 26     db.setDatabaseName("info"); //使用哪个数据库
 27 
 28 
 29     //打开数据库
 30     if( !db.open() ) //数据库打开失败
 31     {
 32         QMessageBox::warning(this, "错误", db.lastError().text());
 33         return;
 34     }
 35 
 36     //设置模型
 37     model = new QSqlTableModel(this);
 38     model->setTable("student");//制定使用哪个表
 39 
 40     //把model放在view
 41     ui->tableView->setModel(model);
 42 
 43     //显示model里的数据
 44     model->select();
 45 
 46     model->setHeaderData(0, Qt::Horizontal, "学号");
 47 
 48     //设置model的编辑模式,手动提交修改
 49     model->setEditStrategy(QSqlTableModel::OnManualSubmit);
 50 
 51     //设置view中的数据库不允许修改
 52     //ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
 53 
 54 }
 55 
 56 Widget::~Widget()
 57 {
 58     delete ui;
 59 }
 60 
 61 void Widget::on_buttonAdd_clicked()
 62 {
 63     //添加空记录
 64     QSqlRecord record = model->record(); //获取空记录
 65     //获取行号
 66     int row = model->rowCount();
 67     model->insertRecord(row, record);
 68 
 69 
 70 }
 71 
 72 void Widget::on_buttonSure_clicked()
 73 {
 74     model->submitAll(); //提交动作
 75 }
 76 
 77 void Widget::on_buttonCancel_clicked()
 78 {
 79     model->revertAll(); //取消所用动作
 80     model->submitAll(); //提交动作
 81 }
 82 
 83 void Widget::on_buttonDel_clicked()
 84 {
 85     //获取选中的模型
 86     QItemSelectionModel *sModel =ui->tableView->selectionModel();
 87     //取出模型中的索引
 88     QModelIndexList list = sModel->selectedRows();
 89     //删除所有选中的行
 90     for(int i = 0; i < list.size(); i++)
 91     {
 92         model->removeRow( list.at(i).row() );
 93     }
 94 
 95 }
 96 
 97 void Widget::on_buttonFind_clicked()
 98 {
 99     QString name = ui->lineEdit->text();
100     QString str = QString("name = '%1'").arg(name);
101 
102     model->setFilter(str);
103     model->select();
104 
105 }
widget.cpp

猜你喜欢

转载自www.cnblogs.com/yuweifeng/p/9403696.html
今日推荐