You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++ Builder中为关联TDBGrid的SQLite TDataSource添加记录?

解决C++ Builder中SQLite添加记录时的数据库锁定问题

核心原因

SQLite是单文件型数据库,同一时间仅支持一个写入操作。当绑定DBGrid的TFDQuery处于打开状态时,数据集会持续持有数据库的读/写锁,此时直接调用ExecSQL或AppendRecord会因锁冲突触发数据库锁定错误。

解决方案一:使用数据集编辑模式(推荐)

通过TDataSet的原生方法添加记录,确保操作流程规范,同时自动同步DBGrid显示:

bool __fastcall TSqLiteDataModule::AddEntry(const sEntryData *entrydata)
{
    try
    {
        // 确保数据集处于激活状态
        if (!FDQuery1->Active)
            FDQuery1->Open();
            
        FDQuery1->Append(); // 进入追加模式
        // 为字段赋值(自增列无需手动设置,SQLite会自动生成)
        FDQuery1->FieldByName("Icon")->AsInteger = entrydata->uIcon;
        FDQuery1->FieldByName("EntryName")->AsString = entrydata->EntryName;
        FDQuery1->FieldByName("Notes")->AsString = entrydata->Notes;
        FDQuery1->Post(); // 提交新记录
        FDQuery1->Refresh(); // 刷新数据集,让DBGrid显示新增内容
        return true;
    }
    catch (Exception &e)
    {
        ShowMessage("添加失败:" + e.Message);
        // 若处于编辑/插入状态,取消未提交的操作
        if (FDQuery1->State == dsEdit || FDQuery1->State == dsInsert)
            FDQuery1->Cancel();
        return false;
    }
}

解决方案二:独立执行SQL语句(避开数据集锁)

如果偏好直接用ExecSQL插入,需临时关闭数据集释放锁,操作完成后重新打开:

bool __fastcall TSqLiteDataModule::AddEntry(const sEntryData *entrydata)
{
    try
    {
        // 记录数据集原状态,操作后恢复
        bool wasActive = FDQuery1->Active;
        if (wasActive)
            FDQuery1->Close();
            
        // 执行插入SQL
        FDConnection->ExecSQL(
            "INSERT INTO Entries(Icon, EntryName, Notes) VALUES (:Icon, :EntryName, :Notes)",
            OPENARRAY(Variant, (entrydata->uIcon, entrydata->EntryName, entrydata->Notes))
        );
        
        // 恢复数据集状态,刷新DBGrid
        if (wasActive)
            FDQuery1->Open();
            
        return true;
    }
    catch (Exception &e)
    {
        ShowMessage("添加失败:" + e.Message);
        return false;
    }
}

额外优化建议

  • 连接参数调整:在TFDConnection的Params中设置LockingMode=NORMAL、SharedCache=False,减少因缓存或锁模式导致的冲突。
  • 事务包裹批量操作:如果有多次插入需求,用事务缩短锁持有时间:
    FDConnection->StartTransaction();
    try
    {
        // 执行批量插入逻辑
        FDConnection->Commit();
    }
    catch(...)
    {
        FDConnection->Rollback();
        throw;
    }
    
  • 自增列处理:无需在AppendRecord中传入0作为自增列值,直接跳过该列即可,SQLite会自动生成序列值。

内容的提问来源于stack exchange,提问作者user3161924

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:35:01