当前位置:   article > 正文

(8)Qt---数据库_qt 数据库

qt 数据库

1. Qt数据库简介

Qt只是作为媒介去操作数据库,本身不具备数据库的功能,因此除了Qt以外,还需要在计算机中安装对应的数据库软件,但是由于SQLite数据库比较轻巧,因此Qt集成了SQLite数据库,此数据库是嵌入式中最常用的数据库。

实际上Qt支持以下类型的数据库产品:

在Qt项目中使用数据库必须在.pro项目配置文件中增加sql模块。

2. 连接与关闭

主要使用到的类是数据库连接类QSqlDatabase(数据库的连接)和数据库错误信息类QSqlError(可能出现的错误信息),涉及的函数有:

  1. // 获得一个基于SQLite的数据库连接对象
  2. QSqlDatabase QSqlDatabase::addDatabase("QSQLITE") [static]
  1. // 设置SQLite数据库文件的名称(不同的数据库此函数表示不同的功能)
  2. // 在运行之后,此文件会在构建目录中生成
  3. void QSqlDatabase::setDatabaseName(const QString & name)
  1. // 打开数据库连接
  2. // 返回值是打开的结果,如果打开失败,可以通过lastError()函数获得错误信息
  3. bool QSqlDatabase::open()
  1. // 获得上一次数据库的错误信息
  2. QSqlError QSqlDatabase::lastError() const
  3. // 可以通过下面的函数把错误信息转换为字符串(实际上这些信息来自于底层数据库)
  4. QString QSqlError::text() const
  1. // 判断连接是否打开
  2. bool QSqlDatabase::isOpen() const
  1. // 关闭连接
  2. void QSqlDatabase::close()

连接成功后会生成数据库文件。

3. 建表

QSqlQuery主要用于执行SQL语句,相关函数如下。

  1. // 执行SQL语句
  2. // 参数是要执行的SQL语句
  3. // 返回值是语句本身执行的结果,并不是数据操作的结果
  4. bool QSqlQuery::exec(const QString & query)
  1. // 用法与之前的同名函数完全相同
  2. QSqlError QSqlQuery::lastError() const

参考建表语句:

CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL);

建表成功后,可以直接到构建目录中使用SQLiteSpy工具打开.db文件验证是否建表成功。

 dialog.h

  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QtWidgets>
  4. #include <QDebug>
  5. #include <QButtonGroup>
  6. #include <QSqlDatabase>
  7. #include <QSqlError>
  8. #include <QSqlQuery>
  9. namespace Ui {
  10. class Dialog;
  11. }
  12. class Dialog : public QDialog
  13. {
  14. Q_OBJECT
  15. public:
  16. explicit Dialog(QWidget *parent = 0);
  17. ~Dialog();
  18. private:
  19. Ui::Dialog *ui;
  20. QButtonGroup *group;
  21. QSqlDatabase db; //数据库连接对象
  22. void connect2Db(); //连接到数据库
  23. void createTable(); //建表
  24. private slots:
  25. void btnsClickedSlot(int); //按钮组点击槽函数
  26. };
  27. #endif // DIALOG_H

dialog.cpp

  1. #include "dialog.h"
  2. #include "ui_dialog.h"
  3. Dialog::Dialog(QWidget *parent) :
  4. QDialog(parent),
  5. ui(new Ui::Dialog)
  6. {
  7. ui->setupUi(this);
  8. group = new QButtonGroup(this);
  9. group->addButton(ui->pushButtonInsert,1);
  10. group->addButton(ui->pushButtonDelete,2);
  11. group->addButton(ui->pushButtonUpdate,3);
  12. group->addButton(ui->pushButtonSelect,4);
  13. connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));
  14. connect2Db();
  15. }
  16. void Dialog::btnsClickedSlot(int id){
  17. if(id == 1){
  18. }else if(id == 2){
  19. }else if(id == 3){
  20. }else if(id == 4){
  21. }
  22. }
  23. Dialog::~Dialog()
  24. {
  25. //如果数据库连接打开了,则关闭
  26. if(db.isOpen()){
  27. db.close();
  28. }
  29. delete ui;
  30. }
  31. void Dialog::connect2Db()
  32. {
  33. //获得一个基于SQLite的数据库连接对象
  34. db = QSqlDatabase::addDatabase("QSQLITE");
  35. db.setDatabaseName("bank_manage.db"); //设置数据库文件的名称
  36. //打开链接
  37. //bool QSqlDatabase::open(); //lasterror函数获得错误信息
  38. if(db.open()){
  39. qDebug()<<"连接打开成功!";
  40. createTable();
  41. }else{
  42. //拿到错误信息
  43. QString text = db.lastError().text();
  44. //展示错误信息
  45. QMessageBox::critical(this,"错误",text);
  46. }
  47. }
  48. void Dialog::createTable()
  49. {
  50. QString sql = "CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL)";
  51. //数据库操作类
  52. QSqlQuery sq;
  53. if(sq.exec(sql)){ //执行SQL的成功or失败
  54. qDebug()<<"建表成功!";
  55. }else{
  56. qDebug()<<sq.lastError().text(); //输出错误信息
  57. }
  58. }

运行结果:

4. 增删改

增删改的操作方法比较相似,需要注意是不要使用拼接的方式创建带参数的SQL语句,原因有:

  • 拼接复杂,容易出错
  • 容易引发SQL注入的安全问题

Qt使用占位符替换的方式“拼接”SQL语句,占位符替换有两种方式:

  • ODBC style (?)
  • Oracle style colon-name 

本次授课使用前者,后者可以查看下面函数的文档。

预处理→绑定→执行

  1. // 预处理带有占位符的SQL语句
  2. // 参数为预处理的SQL语句
  3. // 返回值是预处理的结果
  4. bool QSqlQuery::prepare(const QString & query)
  1. // 添加绑定数据
  2. // 参数为要绑定的数据,各种类型直接传递即可,传递的顺序要按照?的顺序
  3. void QSqlQuery::addBindValue(const QVariant & val)
  1. // 执行预处理的SQL语句
  2. // 语句本身是否成功执行
  3. bool QSqlQuery::exec()

5. 查询

查询与迭代器指针的工作原理类似,相关函数如下。

  1. // 取出结果中的下一个记录,如果没有下一个记录则返回false
  2. bool QSqlQuery::next()
  1. // 按照列序号取出对应的列数据
  2. // 参数是列序号,从0开始
  3. // 返回值是取出的数据,支持各种常见类型的转换
  4. QVariant QSqlQuery::value(int index) const
  1. // 按照列名取出对应的列数据
  2. // 参数是列名
  3. // 返回值是取出的数据,支持各种常见类型的转换
  4. QVariant QSqlQuery::value(const QString & name) const

6.银行管理系统程序代码(包含增删改查)

dialog.h

  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QtWidgets>
  4. #include <QDebug>
  5. #include <QButtonGroup>
  6. #include <QSqlDatabase>
  7. #include <QSqlError>
  8. #include <QSqlQuery>
  9. namespace Ui {
  10. class Dialog;
  11. }
  12. class Dialog : public QDialog
  13. {
  14. Q_OBJECT
  15. public:
  16. explicit Dialog(QWidget *parent = 0);
  17. ~Dialog();
  18. private:
  19. Ui::Dialog *ui;
  20. QButtonGroup *group;
  21. QSqlDatabase db; //数据库连接对象
  22. void connect2Db(); //连接到数据库
  23. void createTable(); //建表
  24. void insertData(); //插入
  25. void deleteData(); //删除
  26. void updateData(); //更新
  27. void selectAll(); //查询所有
  28. bool isDataExists(int); //判断某个id的数据在不在
  29. private slots:
  30. void btnsClickedSlot(int); //按钮组点击槽函数
  31. };
  32. #endif // DIALOG_H

dialog.cpp

  1. #include "dialog.h"
  2. #include "ui_dialog.h"
  3. Dialog::Dialog(QWidget *parent) :
  4. QDialog(parent),
  5. ui(new Ui::Dialog)
  6. {
  7. ui->setupUi(this);
  8. group = new QButtonGroup(this);
  9. group->addButton(ui->pushButtonInsert,1);
  10. group->addButton(ui->pushButtonDelete,2);
  11. group->addButton(ui->pushButtonUpdate,3);
  12. group->addButton(ui->pushButtonSelect,4);
  13. connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));
  14. connect2Db();
  15. }
  16. void Dialog::btnsClickedSlot(int id){
  17. if(id == 1){
  18. insertData();
  19. }else if(id == 2){
  20. deleteData();
  21. }else if(id == 3){
  22. updateData();
  23. }else if(id == 4){
  24. selectAll();
  25. }
  26. }
  27. Dialog::~Dialog()
  28. {
  29. //如果数据库连接打开了,则关闭
  30. if(db.isOpen()){
  31. db.close();
  32. }
  33. delete ui;
  34. }
  35. void Dialog::connect2Db()
  36. {
  37. //获得一个基于SQLite的数据库连接对象
  38. db = QSqlDatabase::addDatabase("QSQLITE");
  39. db.setDatabaseName("bank_manage.db"); //设置数据库文件的名称
  40. //打开链接
  41. //bool QSqlDatabase::open(); //lasterror函数获得错误信息
  42. if(db.open()){
  43. qDebug()<<"连接打开成功!";
  44. createTable();
  45. }else{
  46. //拿到错误信息
  47. QString text = db.lastError().text();
  48. //展示错误信息
  49. QMessageBox::critical(this,"错误",text);
  50. }
  51. }
  52. void Dialog::createTable()
  53. {
  54. QString sql = "CREATE TABLE customer(id INTEGER PRIMARY KEY,name TEXT,money REAL,rate REAL)";
  55. //数据库操作类
  56. QSqlQuery sq;
  57. if(sq.exec(sql)){ //执行SQL的成功or失败
  58. qDebug()<<"建表成功!";
  59. }else{
  60. //输出错误信息
  61. qDebug()<<sq.lastError().text(); //输出错误信息
  62. }
  63. }
  64. void Dialog::insertData()
  65. {
  66. //如果姓名不输入,引导用户输入
  67. QString name = ui->lineEdit->text();
  68. if(name == ""){
  69. QMessageBox::warning(this,"提示","请输入名称!");
  70. return;
  71. }
  72. int id = ui->spinBox->value();
  73. double money = ui->doubleSpinBoxCK->value();
  74. double rate = ui->doubleSpinBoxLL->value();
  75. //操作类对象
  76. QSqlQuery sq;
  77. //预处理的SQL语句
  78. QString sql = "INSERT INTO customer VALUES(?,?,?,?)";
  79. //预处理
  80. sq.prepare(sql);
  81. //绑定数据(顺序不能乱)
  82. sq.addBindValue(id);
  83. sq.addBindValue(name);
  84. sq.addBindValue(money);
  85. sq.addBindValue(rate);
  86. //真正执行SQL语句,执行的是内部预处理的语句
  87. if(sq.exec()){
  88. QMessageBox::information(this,"通知","成功插入一条数据!");
  89. }else{
  90. QString text = sq.lastError().text();
  91. QMessageBox::warning(this,"提示",text);
  92. }
  93. }
  94. void Dialog::deleteData()
  95. {
  96. int id = ui->spinBox->value();
  97. // 判断数据在不在
  98. if(!isDataExists(id)){
  99. QMessageBox::warning(this,"提示","数据不存在!");
  100. return;
  101. }
  102. QString sql = "DELETE FROM customer WHERE id=?";
  103. QSqlQuery sq;
  104. sq.prepare(sql);
  105. sq.addBindValue(id);
  106. if(sq.exec()){
  107. QMessageBox::information(this,"通知","成功删除一条数据!");
  108. }else{
  109. QString text = sq.lastError().text();
  110. QMessageBox::warning(this,"提示",text);
  111. }
  112. }
  113. void Dialog::updateData()
  114. {
  115. //如果姓名不输入,引导用户输入
  116. QString name = ui->lineEdit->text();
  117. if(name == ""){
  118. QMessageBox::warning(this,"提示","请输入名称!");
  119. return;
  120. }
  121. int id = ui->spinBox->value();
  122. //判断要更新的数据在不在
  123. if(!isDataExists(id)){
  124. QMessageBox::warning(this,"提示","数据不存在!");
  125. return;
  126. }
  127. double money = ui->doubleSpinBoxCK->value();
  128. double rate = ui->doubleSpinBoxLL->value();
  129. //操作类对象
  130. QSqlQuery sq;
  131. //预处理的SQL语句
  132. QString sql = "UPDATE customer SET name=?,money=?,rate=? WHERE id=?";
  133. //预处理
  134. sq.prepare(sql);
  135. //绑定
  136. sq.addBindValue(name);
  137. sq.addBindValue(money);
  138. sq.addBindValue(rate);
  139. sq.addBindValue(id);
  140. //执行
  141. if(sq.exec()){
  142. QMessageBox::information(this,"通知","成功修改一条数据!");
  143. }else{
  144. QString text = sq.lastError().text();
  145. QMessageBox::warning(this,"提示",text);
  146. }
  147. }
  148. void Dialog::selectAll()
  149. {
  150. QString sql = "SELECT * FROM customer";
  151. QSqlQuery sq;
  152. if(sq.exec(sql)){
  153. //清空上次显示的结果
  154. ui->textBrowser->clear();
  155. while(sq.next()){ //判断后面有没有数据
  156. //取出每列的数据
  157. //方式一:按照列序号(0,1,2...)取出
  158. QString id = sq.value(0).toString();
  159. //方式二:按照列名取出
  160. QString name = sq.value("name").toString();
  161. QString money = sq.value("money").toString();
  162. QString rate = sq.value("rate").toString();
  163. QString text;
  164. text = text+id.append("-")+name.append("-")+money.append("-")+rate;
  165. //展示数据
  166. ui->textBrowser->append(text);
  167. }
  168. }else{
  169. QString text = sq.lastError().text();
  170. QMessageBox::warning(this,"提示",text);
  171. }
  172. }
  173. bool Dialog::isDataExists(int id)
  174. {
  175. QString sql = "SELECT * FROM customer WHERE id=?";
  176. QSqlQuery sq;
  177. sq.prepare(sql); //预处理
  178. sq.addBindValue(id); //绑定
  179. sq.exec(); //执行
  180. return sq.next(); //只需要返回后面有没有数据
  181. }

ui界面

 

运行结果

 

 

 

 

 

利用SQLiteSpy.exe查看数据表:

 

 

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号