sqlite3_bind_text对我不起作用,但bind-double可以正常工作

0kjbasz6  于 2023-04-06  发布在  SQLite
关注(0)|答案(2)|浏览(246)

我写了一个小类来处理SQLite准备查询。如果我在SQL中的变量是double,代码运行良好,给出一个值列表。但是当我绑定一个字符串时,我没有得到任何结果,因为sqlite3_step函数立即返回SQLITE_DONE。
失败的查询是`

string prepsql =
        "Select foodname, price, storename from prices \
        join foods on (foods.foodkey = prices.foodkey)  \
        join stores on (stores.storekey = prices.storekey) \
        where foodname = ? order by price";
`

调用函数的C++代码是

PreparedQuery pq(db, prepsql);
    pq.setVariable(1, "Milk");
    pq.execute();

调用SQLite函数的实际代码是

PreparedQuery::PreparedQuery(sqltDatabase db, string query): 
    Query(db, query)    {
         int rc = sqlite3_prepare_v2(db.getDb(), query.c_str(), query.size(),
             &stmt, nullptr);
         checkerr(rc);
    }
//bind a text value to the query
void PreparedQuery::setVariable(int index, string value) {
    string sval = value;
    auto val1 = sval.c_str();
    int rc = sqlite3_bind_text(stmt, 1,val1, sizeof(val1), NULL);
    checkerr(rc);
}
//bind a double value to the query
void PreparedQuery::setVariable(int index, double value) {
    int rc = sqlite3_bind_double(stmt, 1, value);
    checkerr(rc);
}

//execute the query and get back the column names and values
int PreparedQuery::execute() {
        
    while (sqlite3_step(stmt) != SQLITE_DONE){  
        for (int col = 0; col < sqlite3_column_count(stmt); col++) {
            const char* name = sqlite3_column_name(stmt, col);
            const unsigned char* val = sqlite3_column_text(stmt, col);
            std::cout << name << " is " << val << std::endl;
        }
    }
    sqlite3_finalize(stmt);
    return 0;
}

但是,如果我将查询的最后一部分改为使用双精度型

where price > ? order by price";

并为double调用setVariable方法

pq.setVariable(1, 2.00);

查询工作正常,我得到一个匹配查询的行列表。
所以我的sqlite_bind_text调用一定有什么我无法辨别的错误。我可能做错了什么。
这是一台运行Visual Studio Community Edition的Windows 10机器,我于2023年2月22日下载了SQLite3。C++ v20。
我尝试了用引号“Milk”括起来的字符串参数,结果没有什么不同。如果我将查询更改为包含实际字符串而不是问号,

where foodname = \"Milk\" order by price";

查询正确运行。
如果我使用相同的数据库在SQLite Studio中运行包含准备好的查询的问号,它会弹出一个地方来输入变量值:例如Milk,不带引号,它可以正常运行。
我有一种感觉,我错过了一些明显的东西,但我还没有发现它。建议欢迎。

6xfqseft

6xfqseft1#

两处修改使其最终成功:我将字符串sval作为类级别的变量,这样它就不会被删除;使用strlen而不是sizeof。

sval = value;  //class level variable
const char* val1 = sval.c_str();
int rc = sqlite3_bind_text(stmt, 1,val1, strlen(val1), NULL);
z9smfwbn

z9smfwbn2#

很可能,问题是在实际执行SQL之前,C++ string对象中的字符串被移动或删除。尝试传递SQLITE_TRANSIENT以将字符串标记为“临时”,以便SQLite创建自己的内部副本。

int rc = sqlite3_bind_text(stmt, 1,val1, sizeof(val1), SQLITE_TRANSIENT);

相关问题