首页 > 解决方案 > c++ sqlite3更新查询未提交

问题描述

我正在学习如何为 c++ 使用 sqlite3 库,到目前为止,我设法执行 SELECT 查询并创建新表,但似乎更新/插入不起作用:

作为模拟测试,我使用的是静态查询(不使用变量):

int rc {0};
char *zErrMsg {0};
sql = "UPDATE tag_list set name = 'foo' where ID=16; " \
      "SELECT * from tag_list";

rc = sqlite3_exec(this->db_ptr, sql, callback, (void*)data, &zErrMsg);

if( rc != SQLITE_OK ) {
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
} else {
    fprintf(stdout, "Operation done successfully\n");
}

我的回调函数是:

static int callback(void *data, int argc, char **argv, char **azColName){
   int i;
   fprintf(stderr, "%s: ", (const char*)data);

   for(i = 0; i<argc; i++) {
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

输出:

id = 14
name = computer
last_update = 123

id = 16
name = foo
last_update = 1

Operation done successfully

当我直接查询数据库时,这就是我得到的:

╔════╦══════════╦═════════════╗
║ ID ║   name   ║ Last_update ║
╠════╬══════════╬═════════════╣
║ 14 ║ computer ║         123 ║
║ 16 ║ s        ║           1 ║
╚════╩══════════╩═════════════╝

我使用 sqlite3_get_autocommit 检查并返回 1,据我了解,这意味着它是自动提交的。

我可以从外部更新行,它只发生在代码中。

tl; dr:我正在尝试更新我创建的表中的名称,但似乎没有提交更改。

我希望有更多经验的人以前遇到过这个并且知道如何绕过这个。

标签: c++sqlite

解决方案


所以我设法找到了我的问题,它根本不在发布的代码中..

我的问题是我将我的 sqlite3 指针传递给另一个类,认为它是通过引用而不是副本。

上面的代码形式来自我的另一个类,我可以在其中查询数据,但不能写入/更改。

如 SQLite3 文档 ( https://www.sqlite.org/lockingv3.html ) 中所述:

一次只有一个进程可以持有 RESERVED 锁。但是其他进程可以在保留保留锁被持有时继续读取数据库。

代码:

主.cpp:

in main() {
 sqlite3 *db_ptr;
 sqlite3_open("test.db",db_ptr);

 ConfigurationManager *config_manager = new ConfigurationManager(db_ptr);
}

配置管理器.cpp:

ConfigurationManager::ConfigurationManager(sqlite3 *db) {
    std::cout << "in constructor" << std::endl;
    this->db_ptr = db;

    if (initialize_db()) {  // initialize_db() creates tables if they don't exist
        std::cout << "Configuration table initialized" << std::endl;
    }


}
int ConfigurationManager::update_rule_last_run(int id) {
    int rc {0};
    char *zErrMsg = 0;
    auto epoch = std::chrono::system_clock::now().time_since_epoch();
    auto epoch_seconds = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();

    std::ostringstream string_stream;
    string_stream << "Update discovery_rules ";
    string_stream << "SET last_run = " << epoch_seconds <<" ";
    string_stream << "Where id = " << id << ";";
    std::string query = string_stream.str();

    std::cout << "- Rule Id " << id << " update command: " << query << std::endl;
    rc = sqlite3_exec(this->db_ptr, query.c_str(), NULL,NULL, &zErrMsg);

    if (rc != SQLITE_OK) {
        std::cout << "Error occured while polling discovery rules: " << zErrMsg << std::endl;
        throw std::exception();
    }

    return 0;
}

一个可能的解决方案(我发现的一个)是为 sqlite3 创建一个包装类并管理来自它的所有查询。


推荐阅读