C++ sqlite3 绑定(bind)参数

标签 c++ sqlite

我只用了几天 C++ 的 sqlite3 库,但它给我带来了很大的挫败感。

我想定义一个参数化的 CREATE TABLE,然后将参数绑定(bind)到它。它看起来像这样:

const char[] CREATE_SQL = 
  "CRAETE TABLE t1 ("
  "  name VARCHAR(:NAME_LEN)"
  "  other VARCHAR(:OTHER_LEN)"
  ");";

我的想法是,在不同的文件(这个头文件的 .cpp)中,我可以将这些参数绑定(bind)到:

int index = sqlite3_bind_parameter_index(stmt, ":NAME_LEN");
sqlite3_bind_int(stmt, index, _DB_FIELD_SIZE_NAME);

其中 _DB_FIELD_SIZE_NAME 也在别处定义。

我不想将 sprintf() 与包含 %d 而不是 :NAME_LENCREATE_SQL 一起使用和 :OTHER_LEN,因为我可能会更改参数的顺序或添加新的参数,并且我希望保持显式绑定(bind)。

现在,对于这个问题:我的准备不返回 SQLITE_OK,而是导致 sqlite3_stmt 的空指针。这是我拥有的:

sqlite3_stmt *stmt;
const char *pStmt = 0;
if( SQLITE_OK != sqlite3_prepare_v2(*db, CREATE_SQL, -1, &stmt, &pStmt) )
    // throws exception with the sqlite3_errmsg(*db) text

所以,我得到的错误是这样的:

near ":NAME_LEN": syntax error

我做错了什么?我确定数据库连接打开正常。

最佳答案

为了不回答您的问题,sqlite 没有严格的文本列大小调整。出于兼容性考虑,它接受 VARCHAR 类型,但其行为没有差异。

你总是会得到与此等价的东西:

const char *sql = 
  "CREATE TABLE t1 ("
  "  name TEXT"
  "  ,other TEXT"
  ");";

为了回答您的问题,我认为您不被允许这样做。 Sqlite 的替换机制仅适用于通常被视为值参数的内容。

例如,您通常会在 INSERTUPDATE 语句中看到的内容。

const char *sql = "INSERT INTO foo (a,b) VALUES (?1,?);";

我完全不记得您是否可以在 CREATE 语句中执行它们,也许对于默认参数?好久不见了。

我发现 boost::format 比我在必须更改非值参数时尝试过的任何其他解决方案更不可能破坏和创建更清晰的代码。

#include <boost/format.hpp>

// ... 

int instance_id = 42;
const char *sql = "CREATE TABLE type_%1% (a,b);";
boost::str( boost::format(sql) % instance_id );

我肯定会鼓励您避免进行非值参数替换,除非您绝对必须这样做。这是一个维护麻烦且容易出错的过程。

关于C++ sqlite3 绑定(bind)参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8993229/

相关文章:

c++ - GLSL - 给定顶点法线计算表面法线

c++ - cin.fail()的错误处理问题

c++ - 返回默认构造值的模板函数

iphone - 如果我调用此方法,则会收到错误 "database is lock"。我该如何解决这个问题?请帮我

ios - CoreData限制相关实体批量大小

java - 无法从我的 Android 笔记应用程序的列表和数据库中删除笔记

c++ - 函数参数同时继承两种类型

c++ - 如何修复由我尝试调用的求和函数引起的段错误? C++

iphone - iphone 应用程序更新期间的 sqlite DB 待办事项

sqlite - 指示一对多表中的 "canonical"记录