• 界面编程之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
  • 相关阅读:
    PCB 设计文件中哪些可以不做成元件
    IAR 9+ 编译 TI CC2541 出现 Segment ISTACK (size: 0xc0 align: 0) is too long for segment definition.
    每日一条 git 命令行:git clone https://xxxxx.git -b 12.0 --depth 1
    FastAdmin Bootstrap-table 特定某行背景变红
    如何查看 ThinkPHP5.1 的升级说明
    Windows 2008 关闭远程桌面的单用户多会话模式
    来测试一下你的“金耳朵”
    笔记:关于网站的流量攻击
    排序算法视频 《6 分钟演示 15 种排序算法》
    【转】移动web页面支持弹性滚动的3个方案
  • 原文地址:https://www.cnblogs.com/yuweifeng/p/9403696.html
Copyright © 2020-2023  润新知