Qt自带有QODBC驱动(封装了ODBC驱动接口),通过windows平台上提供的ODBC驱动访问支持ODBC的数据库,如Ms Access、SQL Server等 (Windows XP 自带有Access和SQL Server的ODBC Driver)。我们就用QODBC对Access数据库进行访问。
Access数据库后缀名说明
.accdb文件:accdb文件格式用于Office Access 2007 文件格式的文件扩展名,用于取代 MDB 文件扩展名。
.mdb文件:mdb文件格式是Office Access97/2000/2003数据库文件后缀名,是早期Access文件格式。
最开始需要查看自己电脑上access数据库驱动是32位还是64位。查看办法:通过odbc数据源管理器进行查看,odbc数据源管理器分为32位和64位。
控制面板->系统和安全->管理工具
ODBC data sources(32bit): 即odbc数据源32位
ODBC 数据源(64位):
表明
1.电脑只有64位的accesss数据库驱动,没有32位的accesss数据库驱动
2.odbc数据源64位能对64位的accesss数据库驱动进行管理。
安装32位的accesss数据库驱动下载地址:
https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=13255
安装64位的accesss数据库驱动下载地址:
https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=13255
安装32位access数据库驱动后:
知识点:
查看qt支持哪些数据库的驱动
QStringList strlist = QSqlDatabase::drivers();
foreach(QString strdriver,strlist)
{
qDebug() << strdriver << endl;
}
即我们的qt支持这些驱动:QSQLITE、QMYSQL、QMYSQL3、QODBC、QODBC3、QPSQL、QPSQL7
如果是ACCESS数据库,则加载数据使用的驱动是:QODBC
QString strFilter = "access数据库(*.mdb);;SQL Lite数据库(*.db *.db3)";
QString strDBname = QFileDialog::getOpenFileName(this,"选择数据库文件","", strFilter);
m_db = QSqlDatabase::addDatabase("QODBC", "MyAccessDB");
strName = QString("DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};FIL={MS Access};DBQ=%1").arg(strDBname);
m_db.setDatabaseName(strName);
如果是SQL Lite数据库,则加载数据使用的驱动是:QSQLITE
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(strName);
延伸到SQLite数据库
SQLite数据库的特点:
1. ACID事务
2. 零配置 – 无需安装和管理配置
3.储存在单一磁盘文件中的一个完整的数据库
4.数据库文件可以在不同字节顺序的机器间自由的共享
5.支持数据库大小至2TB
6. 足够小, 大致13万行C代码, 4.43M
7. 比一些流行的数据库在大部分普通数据库操作要快
8. 简单, 轻松的API
9. 包含TCL绑定, 同时通过Wrapper支持其他语言的绑定
10. 良好注释的源代码, 并且有着90%以上的测试覆盖率
11. 独立: 没有额外依赖
12. 源码完全的开源, 你可以用于任何用途, 包括出售它
13. 支持多种开发语言,C, C++, PHP, Perl, Java, C#,Python, Ruby等
14. 可以跨平台,支持Windows、MacOS、Linux等。
文件格式为db3文件或db文件。
在windows系统上可以使用SQLite Expert软件操作sqlite数据库。
下载 SQLite Expert软件地址:SQLite administration | SQLite Expert
Qt SQL的API分为不同层:
驱动层
对于QT是基于C++来实现的框架,该层主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁。
SQL API层
对于SQL API 层提供了数据库的访问相关类,其中,QSqlDataBase类进行连接,QSqlQuery完成数据库的交互。除此之外,还有QSqlError、QSqlField、QSqlIndex and QSqlRecord类。
用户接口层
用户接口层的几个类实现将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,他们是更高层次的抽象,主要包括QSqlQureyModel,QSqlTableModel and QSqlRelationalTableModel。
用户接口层的类使用模型/视图框架实现了将数据库中的数据链接到窗口控件上。
QTableView是常用的内容显示视图组件。数据模型类有:QSqlQueryModel 、QSqlTableModel 、QSqlRelationalTableModel
QSqlQueryModel :通过设置SELECT语句查询获取内容,Model数据是只读的,不能进行编辑。所以需要结合QSqlQuery一起使用
QSqlTableModel : 直接设置一个数据表的名称,可以获取数据表的全部记录,结果是可编辑的。直接使用QSqlTableModel,而不需要使用QSqlQuery就可以执行对数据库的操作。
QSqlRelationalTableModel: 编辑一个数据表,将代码字段通过关系与代码表关联,将代码字段的编辑转换为直观的内容选择编辑。
怎给数据库设置密码和输入密码
需要用access软件设置。
登录怎使用用户名密码校验。
输入密码只使用QSqlDatabase类的setPassword函数即可。
void setPassword(const QString& password);
前提工作:
已经创建好mdb数据库。如test.mdb
如果没有,需要使用软件创建,如果没有合适的软件创建数据库。简单粗暴就是ODBC数据源管理程序创建。如创建test.mdb。在obdc数据源管理中,新建test.mdb数据库。这样odbc才能访问mdb数据库。
最好是结合视图模型一起使用,如模型为:QSqlTableModel,视图为:QTableView,数据源为QSqlDatabase。
QSqlQuery
执行任意的SQL语句,直接和数据库打交道,可进行insert、delete、update等操作
优点:
- 完全自由编写和执行sql语句,可做任意的查询和操作
- 性能高,可直接操作数据库结构
- 支持事务
缺点:
- 需要自行处理结果集,较复杂
- 不支持直接编辑。需要自行在程序中处理添加、修改和删除。
适用于:数据库不直接和界面交互。
//绑定sql语句
bool prepare(const QString& query);
void bindValue(const QString& placeholder, const QVariant& val,
QSql::ParamType type = QSql::In);
void bindValue(int pos, const QVariant& val, QSql::ParamType type = QSql::In);
void addBindValue(const QVariant& val, QSql::ParamType type = QSql::In);
//执行sql语句
bool exec();
bool exec(const QString& query);
//执行sql语句后,结果的遍历
bool next();
bool previous();
bool first();
bool last();
//某条数据的字段的值
QVariant value(int i) const;
QVariant value(const QString& name) const;
例如
QSqlQuery query = QSqlQuery(db);
query.clear();
bool ret = query.prepare("select * from User WHERE userId=?");
query.bindValue(0,strid);
bool ok = query.exec();
while(query.next())//每一行的数据
{
QString qvalue = query.value("userId").toString();
QString qvalue1 = query.value("username").toString();
qDebug() << qvalue << qvalue1 <<endl;
}
//执行sql语句后,当前位置的结果,位置由bool next();bool previous();
bool first();bool last();决定。从而知道是某行的数据
QSqlRecord record() const;
//执行sql语句
void setQuery(const QSqlQuery &query);
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase());
//返回当前关联的QSqlQuery 对象
QSqlQuery query() const;
不带参数:
QSqlQuery query = QSqlQuery(db);
query.clear();
bool ret = query.exec("CREATE TABLE User ( userId VARCHAR(20) PRIMARY KEY, username VARCHAR(20) )");
query.clear();
带参数:
QSqlQuery query = QSqlQuery(db);
bool bret = false;
query.clear();
bret = query.prepare("insert into User (userId,username) values (?,?)");
query.addBindValue(strid);
query.addBindValue(strname);
bret = query.exec();
query.clear();
或者
QSqlQuery query = QSqlQuery(db);
query.clear();
query.prepare("delete from User WHERE userId=?");
query.bindValue(0,strid);
bool ok = query.exec();
query.clear();
操作步骤:
- 在.pro文件中添加 QT+=sql //即用QtSql文件下的头文件、源文件
- 引用头文件
#include <QSqlDatabase> //连接数据库
#include <QSqlQuery> //执行各种sql语句
#include <QSqlError> //SQL数据库错误信息
#include <QSqlRecord> //封装数据库记录
#include <QSqlTableModel> //单个数据库表的可编辑数据模型
查看QT 对数据库的驱动的类型的支持(具体项目中,可以不用)
QStringList strlist = QSqlDatabase::drivers();
foreach(QString strdriver,strlist)
{
qDebug() << strdriver << endl;
}
具体实例
连接和打开数据库
int AccessHelper::ConnectDatabase(QSqlDatabase &db, const QString strDBname)
{
if(QSqlDatabase::contains("MyAccessDB"))
{
QSqlDatabase::removeDatabase("MyAccessDB");
}
db = QSqlDatabase::addDatabase("QODBC", "MyAccessDB");
const QString strName(QString("DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};FIL={MS Access};DBQ=%1").arg(strDBname));
db.setDatabaseName(strName);
if (!db.isOpen())
{
if (!db.open())
{
qDebug() << db.lastError().text();
return -1;
}
}
return 0;
}
创建表
int AccessHelper::AddTable(const QSqlDatabase &db, const QString strTablename)
{
QSqlQuery query = QSqlQuery(db);
query.clear();
QString strquery =QString("CREATE TABLE %1 ( %2 VARCHAR(8) PRIMARY KEY, %3 VARCHAR(20) )").arg(strTablename).arg(STRID).arg(STRNAME);
bool ret = query.exec(strquery);
query.clear();
return ret == true ? 0 : -1;
}
插入数据
int AccessHelper::AddData(const QSqlDatabase &db,const QString strTablename, const Strdata data)
{
QSqlQuery query = QSqlQuery(db);
bool bret = false;
query.clear();
QString strquery =QString("insert into %1 (%2,%3) values (?,?)").arg(strTablename).arg(STRID).arg(STRNAME);
bret = query.prepare(strquery);
query.addBindValue(data.strID);
query.addBindValue(data.strName);
bret = query.exec();
query.clear();
return bret == true ? 0 : -1;
}
修改数据
int AccessHelper::MOdifyData(const QSqlDatabase& db,const QString strTablename,const Strdata olddata, const Strdata newdata)
{
QSqlQuery query = QSqlQuery(db);
query.clear();
QString strquery =QString("update %1 set %2=?, %3=? where %4=?").arg(strTablename).arg(STRID).arg(STRNAME).arg(STRID);
bool ok = query.prepare(strquery);
query.bindValue(0,newdata.strID);
query.bindValue(1,newdata.strName);
query.bindValue(2,olddata.strID);
ok = query.exec();
query.clear();
return ok == true ? 0 : -1;
}
删除数据
int AccessHelper::DeleteData(const QSqlDatabase &db, const QString strTablename, const Strdata data)
{
QSqlQuery query = QSqlQuery(db);
query.clear();
QString strquery = QString("delete from %1 WHERE %2=?").arg(strTablename).arg(STRID);
query.prepare(strquery);
query.bindValue(0,data.strID);
bool ok = query.exec();
query.clear();
return ok == true ? 0 : -1;
}
查询
int AccessHelper::FilterData(const QSqlDatabase &db, const QString strTablename, const Strdata data,QList<Strdata> &resultdata)
{
QSqlQuery query = QSqlQuery(db);
query.clear();
QString strquery = QString("select * from %1 WHERE %2=?").arg(strTablename).arg(STRID);
bool ret = query.prepare(strquery);
query.bindValue(0,data.strID);
ret = query.exec();
resultdata.clear();
while(query.next())//每一行的数据
{
Strdata data;
data.strID = query.value(STRID).toString();
data.strName = query.value(STRNAME).toString();
qDebug() << data.strID << ":" << data.strName <<endl;
resultdata.append(data);
}
query.clear();
return ret == true ? 0 : -1;
}
删除表
int AccessHelper::DeleteTable(const QSqlDatabase &db, const QString strTablename)
{
QSqlQuery query = QSqlQuery(db);
query.clear();
QString strquery = QString("drop table %1").arg(strTablename);
bool ret = query.exec(strquery);
query.clear();
return ret == true ? 0 : -1;
}
关闭数据库
void AccessHelper::CloseDatabase(QSqlDatabase &db)
{
if (db.isOpen())
{
db.close();
}
}