QFxQSQLite.h
#ifndef QFXQSQLITE_H
#define QFXQSQLITE_H
#include <QObject>
#include <QStringList>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QTime>
#include <QDateTime>
#include <QtGlobal>
class QFxQSQLite : public QObject
{
Q_OBJECT
public:
QFxQSQLite(QObject *parent);
QFxQSQLite();
~QFxQSQLite();
//获取可以利用的所有SQL驱动
static QStringList getAllDrivers();
// 创造一个数据库名字
static QString createDbNameByTime();
// 由毫秒数 转换为 QTime变量
static QTime getTimeFromMSec(const int msec);
//建立数据库链接,打开创建表
bool createDbConnection(const QString& filePath, const QString& connectionName = "qt_sql_default_connection");
//插入数据
bool insertItem(const int id, const char* buf, const int len);
//更新数据库
bool updateItem(const int id, const int time);//更新 Time(第2列) 通过ID
bool updateItem(const int id, const char* buf, const int len);//更新 Buf (第3列) 通过ID
bool updateItem_ALL(const int id, const int time, const char* buf, const int len);//更新 Buf (第3列) 通过ID
//查询数据
bool getItem(const int id, int &time, char* &Buf, int &lenBuf);
//查询最大ID
bool findMaxID(int &id);
//删除
bool delItem(const int id);
//清空表格
bool delTable();
// 关闭数据库
void closeDb();
private:
QSqlDatabase m_database;
QTime m_StartTime;//记录打开数据库的时间,用于换算插入数据的时间
};
#endif // QFXQSQLITE_H
QFxQSQLite.cpp
#include "QFxQSQLite.h"
#include <QDebug>
#pragma execution_character_set("utf-8")
QFxQSQLite::QFxQSQLite(QObject *parent)
: QObject(parent)
{
}
QFxQSQLite::QFxQSQLite()
{
}
QFxQSQLite::~QFxQSQLite()
{
}
// 静态类 beg
QStringList QFxQSQLite::getAllDrivers()
{
qDebug() << "能够支持的数据库驱动有:";
QStringList str_drivers = QSqlDatabase::drivers();
foreach(QString str_driver, str_drivers)
qDebug() << " " << str_driver.toStdString().c_str();
return str_drivers;
}
QString QFxQSQLite::createDbNameByTime()
{
QString DbName;
QTime cTime = QTime::currentTime();
QDateTime cDTime = QDateTime::currentDateTime();
DbName = cDTime.toString("[yyyyMMdd-hhmmss]") + QString("RTData.db");
qDebug() << "DbName = " << DbName.toStdString().c_str();
return DbName;
}
QTime QFxQSQLite::getTimeFromMSec(const int msec)
{
QTime timeSpan(0, 0, 0, 0);
timeSpan = timeSpan.addMSecs(msec);
qDebug() << "time span: " << timeSpan.toString("hh-mm-ss:zzz");
return timeSpan;
}
// 静态类 beg
bool QFxQSQLite::createDbConnection(const QString& filePath, const QString& connectionName /*= "qt_sql_default_connection"*/)
{
// 如果数据库驱动里没有SQLite,则错误警告
//============
if (!QSqlDatabase::drivers().contains("QSQLITE"))
{
qDebug() << "Error: 系统需添加SQLite数据库驱动" << endl;
return false;
}
// 建立数据库
//============
m_database = QSqlDatabase::addDatabase("QSQLITE", connectionName );
m_database.setDatabaseName(filePath);
m_database.setUserName("NiCai");//对于SQLite无用
m_database.setPassword("123456");//对于SQLite无用
// 打开数据库
//============
if (!m_database.open())
{
qDebug() << "Error: Failed to connect database.\n"
<< m_database.lastError() << endl;
return false;
}
// 创建表格
//============
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
//创建一个名为 RT_Data 的表格,表格包含三列,第一列是id,第二列是time(ms),第三列是Buf(二进制)
QString str_create_SQL = "CREATE TABLE IF NOT EXISTS RTData(Id int primary key, Time int, Buf BLOB )";
sql_query.prepare(str_create_SQL);
if (!sql_query.exec())
{
qDebug() << "Error: Fail to create table.\n"
<< sql_query.lastError() << endl;
return false;
}
// 记录当前创建表格的时间
//============
m_StartTime = QTime::currentTime();
return true;
}
void QFxQSQLite::closeDb()
{
if (m_database.isOpen())
{
qDebug() << "关闭数据库" << endl;
m_database.close();
}
else
{
qDebug() << "数据库没有打开.无法关闭" << endl;
}
}
bool QFxQSQLite::insertItem(const int id, const char* buf, const int len)
{
// Table
//[ Id , Time , Buf ]
QTime cTime = QTime::currentTime();
int msecTime = m_StartTime.msecsTo(cTime);
//qDebug() << "time span(ms): " << msecTime;
QByteArray arrayBuf(buf, len);
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_insert_SQL = "INSERT INTO RTData VALUES (?, ?, ?)";//[ Id , Time , Buf ]
sql_query.prepare(str_insert_SQL);
sql_query.addBindValue( id );//ID
sql_query.addBindValue( msecTime );//Time
sql_query.addBindValue( arrayBuf );//Buf
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("插入数据[%d] - 失败!!!!!!!!", id);
return false;//插入失败
}
qDebug("插入数据[%d] - OK!", id);
return true;
}
bool QFxQSQLite::updateItem(const int id, const int time)
{
QString str_update_SQL = "UPDATE RTData SET Time = :msec WHERE Id = :id";
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
sql_query.prepare(str_update_SQL);
sql_query.bindValue(":msec", time);
sql_query.bindValue(":id", id );
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("更新数据[%d] Time - 失败!!!!!!!!", id);
return false;
}
qDebug("更新数据[%d] Time - OK!", id);
return true;
}
bool QFxQSQLite::updateItem(const int id, const char* buf, const int len)
{
QString str_update_SQL = "UPDATE RTData SET Buf = :ByteArray WHERE Id = :id";
QByteArray arrayBuf(buf, len);
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
sql_query.prepare(str_update_SQL);
sql_query.bindValue(":ByteArray", arrayBuf);
sql_query.bindValue(":id", id);
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("更新数据[%d] buf - 失败!!!!!!!!", id);
return false;
}
qDebug("更新数据[%d] buf - OK!", id);
return true;
}
bool QFxQSQLite::updateItem_ALL(const int id, const int time, const char* buf, const int len)
{
QString str_update_SQL = "UPDATE RTData SET Time = :msec, Buf = :ByteArray WHERE Id = :id";
QByteArray arrayBuf(buf, len);
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
sql_query.prepare(str_update_SQL);
sql_query.bindValue(":msec", time);
sql_query.bindValue(":ByteArray", arrayBuf);
sql_query.bindValue(":id", id);
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("更新数据[%d] time buf - 失败!!!!!!!!",id);
return false;
}
qDebug("更新数据[%d] time buf - OK!", id);
return true;
}
bool QFxQSQLite::findMaxID(int &id)
{
QString str_select_max_SQL = "SELECT MAX(Id) FROM RTData";
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
int max_id = 0;
sql_query.prepare(str_select_max_SQL);
if (!sql_query.exec())
{
qDebug("查询最大ID失败");
qDebug() << sql_query.lastError();
return false;
}
else
{
while (sql_query.next())
{
max_id = sql_query.value(0).toInt();
qDebug("find max ID: %d", max_id );
}
}
id = max_id;
return true;
}
bool QFxQSQLite::delItem(const int id)
{
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_delete_SQL = "DELETE FROM RTData WHERE Id = ?";
sql_query.prepare(str_delete_SQL);
sql_query.addBindValue(id);
if (!sql_query.exec())
{
qDebug("删除[%d] - 失败!!!!!!!!", id);
qDebug() << sql_query.lastError();
return false;
}
qDebug("删除[%d] - OK!", id);
return true;
}
bool QFxQSQLite::delTable()
{
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_clear_SQL = "DELETE FROM RTData";
sql_query.prepare(str_clear_SQL);
if (!sql_query.exec())
{
qDebug("删除-[Table] - 失败!!!!!!!!");
qDebug() << sql_query.lastError();
return false;
}
qDebug("删除-[Table] - OK!");
return true;
}
bool QFxQSQLite::getItem(const int id, int &time, char* &Buf, int &lenBuf)
{//其中char* &Buf,是为了不让传回去的Buf无法使用,这样new的才会有用,不用[引用]就得用 char **pBuf,解决问题。
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_select_SQL = "SELECT * FROM RTData WHERE Id = ?";
sql_query.prepare(str_select_SQL);
sql_query.addBindValue(id);
if (!sql_query.exec())
{
qDebug("getItem[%d] - 失败!!!!!!!!",id);
qDebug() << sql_query.lastError();
return false;
}
else
{
while (sql_query.next())
{
int getID = sql_query.value(0).toInt();
time = sql_query.value(1).toInt();
QByteArray array = sql_query.value(2).toByteArray();
lenBuf = array.size();
Buf = new char[lenBuf];
memcpy(Buf, array.data(), lenBuf);
qDebug("%d,%d, time = %d, lenArry = %d, lenBuf = %d", id, getID, time, array.size(), sizeof(Buf));
for (int i = 0; i < lenBuf; i++)
{
qDebug("%02X", Buf[i]);
}
}
}
qDebug("getItem[%d] - OK!\nTime = %d", id, time);
return true;
}
bool createDbConnection(const QString& filePath, const QString& connectionName = "qt_sql_default_connection");
bool QFxQSQLite::createDbConnection(const QString& filePath, const QString& connectionName /*= "qt_sql_default_connection"*/)
{
// 如果数据库驱动里没有SQLite,则错误警告
//============
if (!QSqlDatabase::drivers().contains("QSQLITE"))
{
qDebug() << "Error: 系统需添加SQLite数据库驱动" << endl;
return false;
}
// 建立数据库
//============
m_database = QSqlDatabase::addDatabase("QSQLITE", connectionName );
m_database.setDatabaseName(filePath);
m_database.setUserName("NiCai");//对于SQLite无用
m_database.setPassword("123456");//对于SQLite无用
// 打开数据库
//============
if (!m_database.open())
{
qDebug() << "Error: Failed to connect database.\n"
<< m_database.lastError() << endl;
return false;
}
// 创建表格
//============
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
//创建一个名为 RT_Data 的表格,表格包含三列,第一列是id,第二列是time(ms),第三列是Buf(二进制)
QString str_create_SQL = "CREATE TABLE IF NOT EXISTS RTData(Id int primary key, Time int, Buf BLOB )";
sql_query.prepare(str_create_SQL);
if (!sql_query.exec())
{
qDebug() << "Error: Fail to create table.\n"
<< sql_query.lastError() << endl;
return false;
}
// 记录当前创建表格的时间
//============
m_StartTime = QTime::currentTime();
return true;
}
建立一个QSqlDatabase
对象m_database
,后续的操作都建立在这个对象上。
这句话SqlDatabase::drivers().contains("QSQLITE")
,是用静态函数SqlDatabase::drivers()
得到一个QStringList
变量,这个变量是返回能够支持的数据库种类,如果不能支持,就返回false
。
QSqlDatabase::addDatabase("QSQLITE", connectionName )
中:
QSQLITE
是SQLite对应的驱动名 connectionName
是自定义的连接名称(如果程序需要处理多个数据库文件的话就会这样)。Qt默认连接名称qt_sql_default_connection
,用if (QSqlDatabase::contains(connectionName))
判断链接是否存在(如果有这个需求的话)。setDatabaseName()
的参数是数据库文件名
(可以包含路径)。如果这个数据库不存在,则会在后续操作时自动创建;如果已经存在,则后续的操作会在已有的数据库上进行。
setUserName()
和setPassword()
是设置用户名和密码,但是对于SQLite
来说没有用。
使用open()
打开数据库,返回值为bool
类型,用于判断成功还是失败。
m_StartTime = QTime::currentTime();
打开数据库成功后,我会记录打开数据库的时间,用于以后记录插入每条记录的时间。
对数据库的操作,都是用SQLite
的语句完成的,把这些指令以QString
类型,通过QSqlQuery::prepare()
函数,保存在QSqlQuery
对象中。也可将指令,以QString
形式直接写在QSqlQuery::exec()
函数的参数中,例如:
sql_query.exec("CREATE TABLE IF NOT EXISTS RTData(Id int primary key, Time int, Buf BLOB )");
创建表格语句:
CREATE TABLE <table_name> (f1 type1, f2 type2,…)
CREATE TABLE
是创建表格的语句,也可用小写create table
;RTData
是表格的名称,可以任意取;括号中是表格的格式,上述指令表明,表格中有三列:
表头
)是Id
,这一列储存的数据类型是int
;Time
,数据类型也是是int
,存放毫秒数
;Buf
,数据类型是BLOB
,用于存放二进制数据(我要存放一个char[]数组,大小为100,但是并不是字符串,里面有效数据有可能为\0
,所以不能用SQLite
中的varchar
数据类型)。如果sql_query.exec()
执行成功,则创建表格成功。
注意:
其中IF NOT EXISTS
是说明:如果已经有了表RTData
就不创建了,不加这句,如果数据库文件中已经有了表RTData
,会报错。
对于QSqlQuery sql_query(m_database);
要用打开的数据库m_database
(QSqlDatabase
类型的变量)进行初始化。如果不这样初始化,会出现"QSqlQuery::prepare: database not open"
的错误。
PS:
扩展讲解varchar
类型。
varchar(30)
数据类型是字符数组,最多有30
个字符(和char(30)
的区别在于,varchar
的实际长度是变化的,而char的长度始终是给定的值)。
bool QFxQSQLite::insertItem(const int id, const char* buf, const int len)
{
// Table
//[ Id , Time , Buf ]
QTime cTime = QTime::currentTime();
int msecTime = m_StartTime.msecsTo(cTime);
//qDebug() << "time span(ms): " << msecTime;
QByteArray arrayBuf(buf, len);//不能用char[]存储,要用QByteArray存储二进制
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_insert_SQL = "INSERT INTO RTData VALUES (?, ?, ?)";//[ Id , Time , Buf ]
sql_query.prepare(str_insert_SQL);
sql_query.addBindValue( id );//ID
sql_query.addBindValue( msecTime );//Time
sql_query.addBindValue( arrayBuf );//Buf
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("插入数据[%d] - 失败!!!!!!!!", id);
return false;//插入失败
}
qDebug("插入数据[%d] - OK!", id);
return true;
}
插入语句:
INSERT INTO <table_name> VALUES (value1, value2,…)
INSERT INTO
是插入语句,RTData
是表格名称,VALUES()
是要插入的数据。
这里用addBindValue
来替代语句中的?
,替代的顺序与addBindValue
调用的顺序相同。
也可以用绑定变量名的方式(名称绑定
,原代码为位置绑定
):
QString str_insert_SQL = "INSERT INTO RTData VALUES (:ID, :Time, :buf)";//[ Id , Time , Buf ]
sql_query.prepare(str_insert_SQL);
sql_query.addBindValue( ":ID", id );//ID
sql_query.addBindValue( ":Time", msecTime );//Time
sql_query.addBindValue( ":buf", arrayBuf );//Buf
sql_query.exec();
注意:
不能用char[]
存储,要用QByteArray
存储二进制
一共有3个函数,用于更新数据,现在只说明全部更新的。
bool QFxQSQLite::updateItem_ALL(const int id, const int time, const char* buf, const int len)
{
QString str_update_SQL = "UPDATE RTData SET Time = :msec, Buf = :ByteArray WHERE Id = :id";
QByteArray arrayBuf(buf, len);
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
sql_query.prepare(str_update_SQL);
sql_query.bindValue(":msec", time);
sql_query.bindValue(":ByteArray", arrayBuf);
sql_query.bindValue(":id", id);
if (!sql_query.exec())
{
qDebug() << sql_query.lastError();
qDebug("更新数据[%d] time buf - 失败!!!!!!!!",id);
return false;
}
qDebug("更新数据[%d] time buf - OK!", id);
return true;
}
更新(修改)的语句是:
UPDATE <table_name> SET <f1=value1>, <f2=value2>… WHERE <expression>
bool QFxQSQLite::getItem(const int id, int &time, char* &Buf, int &lenBuf)
{//其中char* &Buf,是为了不让传回去的Buf无法使用,这样new的才会有用,不用[引用]就得用 char **pBuf,解决问题。
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_select_SQL = "SELECT * FROM RTData WHERE Id = ?";
sql_query.prepare(str_select_SQL);
sql_query.addBindValue(id);
if (!sql_query.exec())
{
qDebug("getItem[%d] - 失败!!!!!!!!",id);
qDebug() << sql_query.lastError();
return false;
}
else
{
while (sql_query.next())
{
int getID = sql_query.value(0).toInt();
time = sql_query.value(1).toInt();
QByteArray array = sql_query.value(2).toByteArray();
lenBuf = array.size();
Buf = new char[lenBuf];
memcpy(Buf, array.data(), lenBuf);//复制数据
}
}
qDebug("getItem[%d] - OK!\nTime = %d", id, time);
return true;
}
查询语句:
SELECT <f1>, <f2>, ... FROM <table_name>
SELECT * FROM <table_name>
SELECT * FROM <table_name> WHERE <expression>
注意:
使用这个函数时,对于char*
是会在函数内部中new
,不要用数组常量,以及注意最后释放掉。
QFxQSQLite myDb;
QString str_path = "D:\\MyDataBase.db";
QString str_connectionName = "q-db";
myDb.createDbConnection(str_path, str_connectionName);//初始化
//插入数据等操作
int i, ID;
char buf[100];
for (ID = 0; ID < 3;ID++)
{
for (i = 0; i < 100; i++)
{
buf[i] = 100 - i +ID ;//获取Buf数据
}
myDb.insertItem(ID, buf, sizeof(buf));//插入数据
}
//查找获取某个ID的变量
int outTime;//输出时间
char *outBuf;//一个未初始化的指针,在调用getItem()时,被new
int lenBuf;
ID = 2;
int maxID;
myDb.findMaxID(maxID);//获取这个表的最大ID,作为上限
qDebug("maxID = %d", maxID);
for (ID = 0; ID <= maxID;ID++)
{
myDb.getItem(ID, outTime, outBuf, lenBuf);
qDebug("ID = %d, Time = %d, buf len = %d\n", ID, outTime, lenBuf);
for (i = 0; i < lenBuf; i++)
{
qDebug("%02X", outBuf[i]);//输出显示,或者使用
}
}
delete[] outBuf;//删除变量,用完了防止内存泄漏,最好释放
bool QFxQSQLite::findMaxID(int &id)
{
QString str_select_max_SQL = "SELECT MAX(Id) FROM RTData";
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
int max_id = 0;
sql_query.prepare(str_select_max_SQL);
if (!sql_query.exec())
{
qDebug("查询最大ID失败");
qDebug() << sql_query.lastError();
return false;
}
else
{
while (sql_query.next())
{
max_id = sql_query.value(0).toInt();
qDebug("find max ID: %d", max_id );
}
}
id = max_id;
return true;
}
用了MAX(<f1>)
的SQL函数语法。
bool QFxQSQLite::delItem(const int id)
{
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_delete_SQL = "DELETE FROM RTData WHERE Id = ?";
sql_query.prepare(str_delete_SQL);
sql_query.addBindValue(id);
if (!sql_query.exec())
{
qDebug("删除[%d] - 失败!!!!!!!!", id);
qDebug() << sql_query.lastError();
return false;
}
qDebug("删除[%d] - OK!", id);
return true;
}
删除语句:
DELETE FROM <table_name> WHERE <expression>
DELETE FROM <table_name> WHERE <f1> = <value>
bool QFxQSQLite::delTable()
{
QSqlQuery sql_query(m_database);//不这样初始化,会出现"QSqlQuery::prepare: database not open"
QString str_clear_SQL = "DELETE FROM RTData";
sql_query.prepare(str_clear_SQL);
if (!sql_query.exec())
{
qDebug("删除-[Table] - 失败!!!!!!!!");
qDebug() << sql_query.lastError();
return false;
}
qDebug("删除-[Table] - OK!");
return true;
}
清空语句:
DELETE FROM <table_name>
void QFxQSQLite::closeDb()
{
if (m_database.isOpen())
{
qDebug() << "关闭数据库" << endl;
m_database.close();
}
else
{
qDebug() << "数据库没有打开.无法关闭" << endl;
}
}
先用isOpen()
判断数据库是否打开,然后在调用close()
进行关闭,这些函数都是QSqlDatabase
的类成员函数。
讲SQLite
的教程:http://www.runoob.com/sqlite/sqlite-tutorial.html
一般查看SQLite
数据库文件的软件有: