一、前言
这篇文章的目的主要是为了总结我的课设项目在编程过程中所用的数据库连接方面的知识,由于之前在数据库连接方面我就写过一个学生管理的项目,连接的是SQL Server2012,我之前写过这方面的连接文章,与之相比,Sqlite在创建后会自动生成一个db文件,利用像Navicat之类的工具可以进行数据操作。与文本文档很相像。我也不想有这么多废话主要是CSDN的审核机制需要一些文字,加上自己有点感悟。
1.Sqlite介绍:
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2021年已经接近有21个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
二、数据库的创建以及连接连接
1.连接数据库
利用qt的QSqlDatabase和QSqlError数据库操作的头文件建立数据库与Qt的连接,并且需要在Pro文件中添加sql,如下:
QT += sql //在pro文件中添加
#include <QSqlDatabase> //QSqlDatabase类处理与数据库的连接
#include <QSqlError> //QSqlError类提供 SQL 数据库错误信息。
//定义数据库名称
QSqlDatabase DB;
//分配数据库类型
DB = QSqlDatabase::addDatabase("QSQLITE");
//创建数据库表
DB.setDatabaseName("vip.db"); //会在编译的文件里面生成 :如下图
if(DB.open())
{
qDebug()<<"open vip.db succeful";
}
else //显示报错信息
{
qDebug()<<"fail to open vip.db"<<DB.lastError();
}
2.其他类型数据库连接语句,以SqlServer为例
#include <QSqlDatabase> //QSqlDatabase类处理与数据库的连接
#include <QSqlError> //QSqlError类提供 SQL 数据库错误信息。
#include <QSqlQuery> //提供了一种执行和操作 SQL 语句的方法。
//定义数据库名称
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC", "QSQLITE"); //数据库驱动类型为SQL Server
qDebug()<<"ODBC driver?"<<db.isValid();
QString dsn = QString::fromLocal8Bit("QTDSN"); //数据源名称
db.setHostName("localhost"); //选择本地主机,127.0.1.1
db.setDatabaseName(dsn); //设置数据源名称
db.setUserName("sa"); //登录用户
db.setPassword("ATS2020"); //密码
if(!db.open()) //打开数据库
{
qDebug()<<db.lastError().text();
QMessageBox::critical(0, QObject::tr("Database error"), db.lastError().text());
return false; //打开失败
}
else
{
qDebug()<<"database open success!";
QSqlQuery query(db); //查询VIPdata表并输出,测试能否正常操作数据库
query.exec("SELECT * FROM VIPdata");
while(query.next())
{
qDebug()<<query.value(0).toInt() <<query.value(1).toString();
}
}
三、数据库的表创建
利用QSqlQuery头文件进行数据库的建表操作
#include <QSqlQuery> //提供了一种执行和操作 SQL 语句的方法。
QString create_vipdata("create table if not exists vipdata(id integer primary key" "autoincrement not null,"
"name text not null,"
"sex text not null,"
"username text not null,"
"password text not null);");
QSqlQuery query;
//判断语句是否出错
if(query.exec(create_vipdata))
{
qDebug()<<"create table goods successful";
}
else
{
qDebug()<<"table goods has already created"<<query.lastError();
}
另外一种sql语句插入的写法
//另外一种sql语句插入的写法
QString sql=QString("select * from user where username='%1'").arg(username);
QSqlQuery query(sql);
四、QTableView显示数据库信息并操作
1.重写父类虚函数
#include <QObject>
#include <QSqlQueryModel>
#include <QSqlQuery> //QSqlQuery类提供了一个用于执行SQL语句和浏览查询的结果集的接口
#include <QMessageBox>
//用户登录界面存储信息:用户名 密码
//功能类,非视图操作 继承父类
class sqlMessage:public QSqlQueryModel
{
public:
sqlMessage(QObject* parent = 0);
/*原作者注释感觉有点秀,保留一下
//重写父类的虚函数
//The model is read-only by default. To make it read-write,
//you must subclass it and reimplement setData() and flags().*/
bool setData(const QModelIndex &index,const QVariant &value,int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
//更新数据信息
void refresh();
private:
//根据需求定义的内部的字段相关接口
bool setPassWord(int passwordId,const QString &passWord);
};
sqlMessage.h
#include <QObject>
#include <QSqlQueryModel>
#include <QSqlQuery> //QSqlQuery类提供了一个用于执行SQL语句和浏览查询的结果集的接口
#include <QMessageBox>
//用户登录界面存储信息:用户名 密码
//功能类,非视图操作 继承父类
class sqlMessage:public QSqlQueryModel
{
public:
sqlMessage(QObject* parent = 0);
/*原作者注释感觉有点秀,保留一下
//重写父类的虚函数
//The model is read-only by default. To make it read-write,
//you must subclass it and reimplement setData() and flags().*/
bool setData(const QModelIndex &index,const QVariant &value,int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
//更新数据信息
void refresh();
private:
//根据需求定义的内部的字段相关接口
bool setPassWord(int passwordId,const QString &passWord);
};
sqlMessage.cpp
#include "sqlmessage.h"
#include <QDebug>
sqlMessage::sqlMessage(QObject* parent)
{
parent = nullptr;
}
//可编辑的列数
bool sqlMessage::setData(const QModelIndex &index, const QVariant &value, int role)
{
role = Qt::EditRole;
if(index.column() < 4)
{
return false;
}
//获取id
QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(),0);
int id = data(primaryKeyIndex).toInt();
bool isok = false;
if(index.column() == 4)
{
//要根据字段的类型来设置对象的值
isok = setPassWord(id,value.toString());
}
refresh();
return isok;
}
//改变其可编辑性质
Qt::ItemFlags sqlMessage::flags(const QModelIndex &index) const
{
//获取当前目录的标志
Qt::ItemFlags flags = QSqlQueryModel::flags(index);
//根据自己表的列数的情况设定标志,第一列和第二列可以进行编辑
if(index.column() == 4)
{
flags |= Qt::ItemIsEditable;
}
return flags;
}
void sqlMessage::refresh()
{
setQuery("select * from vipdata");
//设置表列名
setHeaderData(0,Qt::Horizontal,QObject::tr("会员序号"));
setHeaderData(1,Qt::Horizontal,QObject::tr("会员姓名"));
setHeaderData(2,Qt::Horizontal,QObject::tr("会员性别"));
setHeaderData(3,Qt::Horizontal,QObject::tr("会员账号"));
setHeaderData(4,Qt::Horizontal,QObject::tr("会员密码"));
}
//重写更新密码接口
bool sqlMessage::setPassWord(int passwordId, const QString &passWord)
{
/*如果你想要同时插入许多条记录,一个有效的方法就是将查询语句和真实的值分离,
* 这个可以使用占位符来实现。Qt支持两种占位符:
* 名称绑定和位置绑定。下面是一个名称绑定的示例:
//方法1:替换
//query.prepare("update vipdata set password = pW where id = PWid");
//query.bindValue("pW",passWord);
//query.bindValue("PWid",passwordId);*/
QSqlQuery query;
//方法2: 位置
query.prepare("update vipdata set password = ? where id = ?");
query.addBindValue(passWord);
query.addBindValue(passwordId);
return query.exec();
}
2.自定义图表绑定数据库与图
利用QSqlTableModel和QTableView进行两者的关系建立
#include <QSqlTableModel> //用来显示数据库中数据表的数据,实现对数据的编辑、插入、删除等操作。实现数据的排序和过滤
#include <QTableView> //创建QTableView表格的时,除了创建QTableView对象还需要创建对应的Model对象
sqlMessage *vipmodel;
vipmodel = new sqlMessage();
//2.接着创建一个视图对象
QTableView *vipview = new QTableView;
settabViewModel(vipview,vipmodel);
//设置tab视图表并读取数据
void MainWindow::settabViewModel(QTableView *view, QSqlQueryModel *querymodel)
{
//1.首先创建一个可编辑的model对象
if(querymodel == vipmodel)
{
querymodel->setQuery("select * from vipdata");
querymodel->setHeaderData(0,Qt::Horizontal,QObject::tr("会员序号"));
querymodel->setHeaderData(1,Qt::Horizontal,QObject::tr("会员姓名"));
querymodel->setHeaderData(2,Qt::Horizontal,QObject::tr("会员性别"));
querymodel->setHeaderData(3,Qt::Horizontal,QObject::tr("会员账号"));
querymodel->setHeaderData(4,Qt::Horizontal,QObject::tr("会员密码"));
view = ui->Vip_tableView;
}
//设置表头
view->setModel(querymodel);
//设置全部自动列宽
view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
//设置启用表排序
view->setSortingEnabled(true);
/* 设置列宽的几种方法
view->horizontalHeader()->setMinimumSectionSize(100);//设置最小列宽
view->horizontalHeader()->setMaximumSectionSize(100);//设置最大列宽
//设置单行自动列宽
view->horizontalHeader()->setSectionResizeMode(2,QHeaderView::Stretch);
//全部自适应列宽
view->resizeColumnsToContents();
//设置列宽
view->setColumnWidth(0,150);
view->setColumnWidth(1,150);
view->setColumnWidth(2,100);
view->setColumnWidth(3,100);
view->setColumnWidth(4,100);*/
}
五、登录信息读取
Qt的信号和槽函数机制
//登录设置
void Login::on_btn_login_clicked()
{
QSqlQuery query(adminView->DB);
QString username_true = ui->line_username->text();
QString password_true = ui->line_pwd->text();
if(username_true.isEmpty())
{
QMessageBox::warning(this,"登录提示","账户不能为空");
}
else if(password_true.isEmpty())
{
QMessageBox::warning(this,"登录提示","密码不能为空");
}
else
{
QString sql = QString("select * from admin where username = '%1' ").arg(username_true);
query.exec(sql);
if(query.next())
{
qDebug()<<sql;
QMessageBox::information(this,"登录提示","登录成功");
ui->line_username->clear();
ui->line_pwd->clear();
this->hide();
adminView->show();
}
else if(username_true.isEmpty() == false && password_true.isEmpty() == false)
{
QMessageBox::warning(this,"登录提示","用户名或密码错误");
}
else
{
qDebug()<<"查询管理员表失败"<<query.lastError();
}
}
}