SQLITE3数据库读写助手(3)
概述
- 本文将介绍前文中类SqliteExt的用法
- SqliteExt类功能就三大类:
- 读取slqite中表格的数据
- 写入用户表格中的数据到文件
- 其他功能: 执行sql语句接口......
- 思路: 获取数据库中表每个字段的类型,根据类型移动指针给结构体赋值
- 存放数据的内存需要按照1字节对齐, 例如,下面的结构体stTableCommonIdStr存放表common中的数据, 需要设置1字节对齐
#pragma pack(1)
struct stTableCommonIdStr
{
int id_;
QString name_;
};
#pragma pack()
而表common的结构为:
表common中的数据为
-
SqliteExt的特点(相对常规数据库读写)
- 读取不用调用方编写sql语句, 模块内部自动完成
- 写入数据不用调用方编写sql语句, 模块内自动完成
-
SqliteExt不足
后期有时间再优化与改进,先把V1.00.000开发出来, 为后面重构铺垫。- 目前支持的数据库字段较少,包括: INTEGER, TEXT , DOUBLE
- 基于Qt实现,不满足通用c++使用场景
设计之初
- sqlite数据库内容,无论是读取还是写入,都需要手动编写sql语句交由特定的函数执行
- 如果新增字段, 就需要编写对应的字段的读写,如果遗漏, 则无法完成对应的功能
- 单个项目的配置项可能很多,编写sql语句较为麻烦
- 多个项目使用, 无法达到复用的目的
- 于是,读写任意sqlite数据库表数据的念头产生了
- 自己用的都是小项目, 使用sqlite作为配置文件,简单方便,由于项目逐渐增多,项目的配置维护成本增加
SqliteExt 使用顺序
按照下面的顺序:
- A. 初始化,传递指定的数据库文件及相关参数
- B. 读写表数据
- C. 师傅资源
SqliteExt 头文件函数介绍
initialized_
功能
- 初始化函数,需要调用该函数完成模块初始化后, 方可读写数据库中的内容
使用范例
/// 0. 读取界面当前选择的是哪种
oct_sqlite::stSQLInit st_init;
{
/// 指定打开的数据库文件
st_init.str_sqlite_file_ = str_file;
/// 指定数据库的编辑策略
st_init.en_es_ = oct_sqlite::ES_MANUAL_SUBMIT;
/// 本次需要读取数据库中的哪种数类型
st_init.en_tt_ = static_cast<oct_sqlite::enTableType>(ui.combo_load_type->itemData(ui.combo_load_type->currentIndex()).toInt());
}
/// 1. 执行初始化
int sql_ext_init_ret = psqlite_ext_->initialized_(st_init);
/// 2. 检查初始化结果
if (0 != sql_ext_init_ret)
{
return;
}
carry_on_sql_
功能
- 执行sql语句
函数原型
/// -------------------------------------------------------------------------------
/// @brief: 执行sqlite语句
/// @param: const QString & str_sql - sql语句
/// @param: const QString & str_table_name - 对数据库的那张表执行
/// @ret: int
/// 0 - 成功
/// 1 - 失败, 数据库没有初始化
/// 2 - 失败, 参数str_sql 为空
/// 3 - 失败, 数据库中没有[str_table_name]这张表
/// 5 - 失败, 对应的数据库model没有得到
/// 6 - 失败, sql语句错误
/// 7 - 失败, sql语句执行失败,请检查sql语句
/// -------------------------------------------------------------------------------
int carry_on_sql_(const QString& str_sql, const QString& str_table_name) noexcept;
sql_record_
功能
- 获取sql语句的执行结果
原型
/// -------------------------------------------------------------------------------
/// @brief: 获取sql语句执行结果
/// @param: const QString & str_sql - 对应的sql语句
/// @param: const QString & str_table_name - 操作哪张表
/// @ret: QT_NAMESPACE::QSqlQuery*
/// nullptr - sql语句或者没有[str_table_name]对应的表格, 或者创建对应的model错误
/// != nullptr - 成功
/// -------------------------------------------------------------------------------
QSqlQuery* sql_record_(const QString& str_sql, const QString& str_table_name) noexcept;
uninitialized_
功能
- 释放模块资源,退出前请显示调用
原型
///-------------------------------------------------------------------------------
/// @brief: 释放
/// @ret: void
///
/// -------------------------------------------------------------------------------
void uninitialized_() noexcept;
mapTable
功能
- 调用**initialized_**函数后, 调用该函数,可获得当前表格中的数据结构
原型
/// -------------------------------------------------------------------------------
/// @brief: 获取当数据库中的表
/// @ret: oct_sql::mapTable&
///
/// -------------------------------------------------------------------------------
const mapTable& map_table_() noexcept;
- 其中, **mapTable**的结构的定义如下
/// ----------------------------------------------------------------------------------------
/// @brief: 操作model
/// ----------------------------------------------------------------------------------------
struct stTableModelView_
{
/// model
QSqlTableModel* pmodel_ = nullptr;
/// view
QTableView* pview_ = nullptr;
void set_model_to_view_()
{
if (pview_)
{
pview_->setModel(pmodel_);
}
}
void del_()
{
if (pmodel_)
{
delete pmodel_;
pmodel_ = nullptr;
}
if (pview_)
{
delete pview_;
pview_ = nullptr;
}
}
};
using stTableModelView = stTableModelView_;
/// ----------------------------------------------------------------------------------------
/// @brief: 保存tableName
/// ----------------------------------------------------------------------------------------
/// <表名,model_view>
using mapTable = QMap<QString, stTableModelView>;
- **mapTable**以表的名称作为key, 将对应表格的数据model和view保存下来
用法范例
/// 2 初始化成功, 显示到界面
const oct_sqlite::mapTable& map_sqlite_table = psqlite_ext_->map_table_();
/// 3. 表格逐个显示
int index = 0;
for (auto table_it = map_sqlite_table.begin(); table_it != map_sqlite_table.end(); ++table_it)
{
ui.tabWidget->addTab(table_it->pview_, table_it.key());
ui.tabWidget->setTabIcon(ui.tabWidget->count() - 1, QIcon(":/png/table.png"));
}
table_
功能
- 读取当前数据库中名为str_table_name的参数
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取当前数据库中名为str_table_name的参数,
/// @param: const QString str_table_name - 读取哪张表
/// @param: stTableModelView * pout_tmv - 读取结果存放地址, 内部不会赋值, 外部赋值
/// @ret: int
/// 0 - 成功
/// 1 - 失败,参数[pout_tmv]为nullptr
/// 2 - 失败, 数据库中没有名为【str_table_name】的表格
/// -------------------------------------------------------------------------------
int table_(const QString str_table_name, stTableModelView* pout_tmv) noexcept;
下面开始介绍数据读写相关函数
table_data_
功能
- 读取str_table_name中的数据到pdata
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取str_table_name中的数据到pdata
/// @param: const QString & str_table_name - 哪张表
/// @param: void * pdata - 数据存放地址
/// @ret: int
/// 0 - 成功
/// 1 - 失败, 参数中的[pdata]为空,
/// 2 - 失败, 参数中【str_table_name】的表没有在当前的数据库中
/// 3 - 失败, 无法操作当前表的model
/// 5 - 失败, 查询数据库失败
/// 6 - 失败, 参数[str_table_name]的表格为空表
/// 7 - 失败, 无法获取表格的行数
/// -------------------------------------------------------------------------------
int table_data_(const QString& str_table_name, void* pdata) noexcept;
说明
- 该函数将**str_table_name**表中的数据全部读入到**pdata**的内存中
用法
const int row_count = 2;
st_commom_str st_str[row_count];
/// 执行读取
int ret = common_sql_.table_data_("common", (void*)(&st_str));
for (int index = 0; index < row_count; ++index)
{
qDebug() << "====================================";
qDebug() << "index=" << index;
qDebug() << "id=" << st_str[index].id_;
qDebug() << "name=" << st_str[index].name_;
qDebug() << "db=" << st_str[index].db_;
}
table_data_some_columns_
功能
- 读取[str_table_name]表格中指定列的数据
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取表格str_table_name中map_read_column列的数据到pdata中
/// @param: const QString & str_table_name - 读取哪张表
/// @param: void * pdata - 存放读取结果
/// @param: const mapUIntUInt & map_read_column - 那些列需要读取
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
int table_data_some_columns_(const QString& str_table_name, void* pdata, const mapUIntUInt& map_read_column) noexcept;
用法
oct_sqlite::mapUIntUInt map_read_column_index;
map_read_column_index.emplace(1, 1);
stTableCommonStr st_common_data;
int read_ret = common_sql_.table_data_some_columns_("common", (void*)&st_common_data, map_read_column_index);
qDebug() << "ret=" << read_ret;
qDebug() << "read_result:\n" << "zs=" << st_common_data.name_zs_ << "\nls=" << st_common_data.name_ls_ << "\n\n------end_commom_-------";
table_data_except_columns_
功能
- 读取表格str_table_name中 不在map_read_column列的数据到pdata中
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取表格str_table_name中 不在map_read_column列的数据到pdata中
/// @param: const QString & str_table_name - 哪张表
/// @param: void * pdata - 数据存放
/// @param: const mapUIntUInt & map_read_column - 那些列不用读取
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
int table_data_except_columns_(const QString& str_table_name, void* pdata, const mapUIntUInt& map_except_column);
用法
oct_sqlite::mapUIntUInt map_except_column_index;
/// 不读取第二列
map_except_column_index.emplace(2, 2);
stTableCommonIdStr st_common_data[2];
int read_ret = common_sql_.table_data_except_columns_("common", (void*)&st_common_data, map_except_column_index);
qDebug() << "ret=" << read_ret;
for (int index = 0; index < 2; ++index)
{
qDebug() << "id=" << st_common_data[index].id_ << ", name=" << st_common_data[index].name_zs_;
}
submit_
功能
- 初始化参数指定为: ES_MANUAL_SUBMIT , 调用该函数将界面输入写入文件
原型
/// -------------------------------------------------------------------------------
/// @brief: 初始化参数指定为: ES_MANUAL_SUBMIT , 调用该函数
/// @param: const QString & str_table_name - 哪张表需要提交
/// @ret: int
/// 0 - 成功
/// 1 - 失败, 没有找到
/// 2 - 失败,没有对应的model
/// 3 - 失败, 提交失败
/// -------------------------------------------------------------------------------
int submit_(const QString& str_table_name) noexcept;
用法
int ret = psqlite_ext_->submit_(str_table_name);
QString str_hint;
if (0 != ret)
{
str_hint = tr("failed to submit");
}
else
{
str_hint = tr("succeed to submit");
}
table_data_map_
功能
- 将表格中的数据全部读入map中,其中,map的key就是表格的主键
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取【str_table_name】中的数据,将结果存放到[pout_map]中
/// @param: const QString str_table_name - 哪张表
/// @param: std::map<TKey,TValue> * pout_map - 存放表数据的map, 外部分配空间, 函数内仅仅赋值,
/// @param: const int ui_key_column_index - map的TKey所在列, 从0开始数
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
template<class TKey, class TValue>
int table_data_map_(const QString str_table_name, std::map<TKey, TValue>* pout_map, const int ui_key_column_index) noexcept;
用法
/// 执行读取
std::map<int, udp_channel> map_udp_channel;
int ret = common_sql_.table_data_map_<int, udp_channel>("udp_channel", &map_udp_channel, 0);
int map_count = map_udp_channel.size();
for (std::map<int, udp_channel>::iterator find_it = map_udp_channel.begin(); find_it != map_udp_channel.end(); ++find_it)
{
qDebug() << "====================================";
qDebug() << "id=" << find_it->second.id_ <<", name=" << find_it->second.name_ << ", dest_ip=" << find_it->second.dest_ip_ << ", dest_port=" << find_it->second.dest_ip_;
++find_it->second.port_;
}
table_data_map_some_columns_
功能
- 只读取map_read_column_index列中的数据到pdata中
原型
/// -------------------------------------------------------------------------------
/// @brief: 只读取map_read_column_index列中的数据到pdata中
/// @param: const QString str_table_name - 读取哪张表
/// @param: std::map<TKey,TValue> * pout_map - 用于读取内容存放
/// @param: const int ui_key_column_index - 主键再第几列, 从0开始数
/// @param: const mapUIntUInt & map_read_column_index - 读取表格的哪些列, 从0开始数
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
template<class TKey, class TValue>
int table_data_map_some_columns_(const QString str_table_name, std::map<TKey, TValue>* pout_map, const int ui_key_column_index, const mapUIntUInt& map_read_column_index) noexcept;
table_data_map_except_columns_
功能
- 读取不在map_read_column_index列中的数据到pdata中
原型
/// -------------------------------------------------------------------------------
/// @brief: 读取不在map_read_column_index列中的数据到pdata中
/// @param: const QString str_table_name - 读取哪张表
/// @param: std::map<TKey,TValue> * pout_map - 用于读取内容存放
/// @param: const int ui_key_column_index - 主键再第几列, 从0开始数
/// @param: const mapUIntUInt & map_read_column_index - 不读取表格的哪些列, 从0开始数
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
template<class TKey, class TValue>
int table_data_map_except_columns_(const QString str_table_name, std::map<TKey, TValue>* pout_map, const int ui_key_column_index, const mapUIntUInt& map_read_except_column_index) noexcept;
update_table_
功能
- 将数据写入数据库,注意: pdata中的行数应该与数据库中表的数据相同,否则,将返回非0
原型
/// -------------------------------------------------------------------------------
/// @brief: 将数据写入数据库,注意: pdata中的行数应该与数据库中表的数据相同,否则,将返回非0
/// @param: const QString str_table_name - 哪张表
/// @param: void * pdata - 带写入数据的起始地址
/// @param: const uint key_index - 主键在哪一列,从0 开始数,
/// @ret: int
/// 0 - 成功
/// 1 - 失败, 参数pdata为空
/// 2 - 失败, 无法获取对应表
/// -------------------------------------------------------------------------------
int update_table_(const QString str_table_name, void* pdata, const uint key_index) noexcept;
用法
qDebug() << "================ read_table AAAAAA ====================";
const int row_count = 2;
st_commom_str st_str[row_count];
/// 执行读取
int ret = common_sql_.table_data_("common", (void*)(&st_str));
for (int index = 0; index < row_count; ++index)
{
qDebug() << "====================================";
qDebug() << "index=" << index;
qDebug() << "id=" << st_str[index].id_;
qDebug() << "name=" << st_str[index].name_;
qDebug() << "db=" << st_str[index].db_;
}
/// write
st_str[0].db_ = 1122.0f;
st_str[1].db_ = 5566.0f;
ret = common_sql_.update_table_("common", &st_str, 0);
qDebug() << "\n\n update_result=" << ret << "\n\n";
update_table_some_columns_
功能
- 只更新map_update_column_index中的列到数据库
原型
/// -------------------------------------------------------------------------------
/// @brief: 只更新map_update_column_index中的列到数据库
/// @param: const QString str_table_name - 更新哪张表
/// @param: void * pdata - 待写入的数据
/// @param: const uint key_index - 表格的主键再第几列,从0开始数
/// @param: const mapUIntUInt map_update_column_index - 要写入那些列
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
int update_table_some_columns_(const QString str_table_name, void* pdata, const uint key_index, const mapUIntUInt map_update_column_index) noexcept;
update_table_except_columns_
功能
- 只更新不在map_update_column_index中的列到数据库
原型
/// -------------------------------------------------------------------------------
/// @brief: 只更新不在map_update_column_index中的列到数据库
/// @param: const QString str_table_name - 更新哪张表
/// @param: void * pdata - 待写入的数据
/// @param: const uint key_index - 表格的主键再第几列,从0开始数
/// @param: const mapUIntUInt map_update_column_index - 不写入那些列
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
int update_table_except_columns_(const QString str_table_name, void* pdata, const uint key_index, const mapUIntUInt map_except_column_index) noexcept;
update_table_map_
功能
- 将pmap_data中的数据写入[str_table_name]中, 注意: pmap_data中的行数应该与数据库中表的数据相同,否则,将返回6
原型
/// -------------------------------------------------------------------------------
/// @brief: 将pmap_data中的数据写入[str_table_name]中, 注意: pmap_data中的行数应该与数据库中表的数据相同,否则,将返回6
/// @param: const QString str_table_name - 对应书库中表的名字
/// @param: const std::map<TKey, TValue> * pmap_value - 待写入数据内容
/// @param: const uint key_column_index - str_table_name的主键在哪一列, 从0 开始数
/// @ret: int
///
/// -------------------------------------------------------------------------------
template<typename TKey, typename TValue>
int update_table_map_(const QString str_table_name, const std::map<TKey, TValue>* pmap_data, const uint key_column_index) noexcept;
update_table_map_some_columns_
功能
- 将map_update_column_index中的数据写入[str_table_name]中, 且只写入【map_update_column_index】中的列数据,
原型
/// -------------------------------------------------------------------------------
/// @brief: 将map_update_column_index中的数据写入[str_table_name]中, 且只写入【map_update_column_index】中的列数据,
/// @param: const QString str_table_name - 对应书库中表的名字
/// @param: const std::map<TKey, TValue> * pmap_value - 待写入数据内容
/// @param: const uint key_column_index - str_table_name的主键在哪一列, 从0 开始数
/// @param: const mapUIntUInt map_update_column_index - 要写入哪些列的数据
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
template<typename TKey, typename TValue>
int update_table_map_some_columns_(const QString str_table_name, const std::map<TKey, TValue>* pmap_data, const uint key_column_index, const mapUIntUInt& map_update_column_index) noexcept;
update_table_map_except_columns_
功能
- 将不在map_except_column_index中的数据写入[str_table_name]中, 且只写入【map_update_column_index】中的列数据,
原型
/// -------------------------------------------------------------------------------
/// @brief: 将不在map_except_column_index中的数据写入[str_table_name]中, 且只写入【map_update_column_index】中的列数据,
/// @param: const QString str_table_name - 对应书库中表的名字
/// @param: const std::map<TKey, TValue> * pmap_value - 待写入数据内容
/// @param: const uint key_column_index - str_table_name的主键在哪一列, 从0 开始数
/// @param: const mapUIntUInt map_update_column_index - 不要写入哪些列的数据
/// @ret: int
/// 0 - 成功
/// 其他 - 失败
/// -------------------------------------------------------------------------------
template<typename TKey, typename TValue>
int update_table_map_except_columns_(const QString str_table_name, const std::map<TKey, TValue>* pmap_data, const uint key_column_index, const mapUIntUInt& map_except_column_index) noexcept;
下面是一些其他支撑函数
file_suffix_is_right_
功能
- 检查参数中的后缀是否为支持的后缀
原型
/// -------------------------------------------------------------------------------
/// @brief: 检查文件后缀是否为可支持类型
/// @param: const QString & str_suffix - 待检查的文件后缀
/// @ret: bool
/// true - 支持,
/// false - 不支持
/// -------------------------------------------------------------------------------
bool file_suffix_is_right_(const QString& str_suffix) noexcept;
suffix_
功能
- 获取支持的文件后缀字符串
原型
/// -------------------------------------------------------------------------------
/// @brief: 将支持的文件以字符串的形式返回
/// @ret: QT_NAMESPACE::QString
/// -------------------------------------------------------------------------------
QString suffix_() noexcept;
完整范例
- 下一节开启