2

我只玩了几天的用于 C++ 的 sqlite3 库,但这让我非常沮丧。

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

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

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

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

其中 _DB_FIELD_SIZE_NAME 也在别处定义。

我不想使用sprintf()with CREATE_SQLcontains%d而不是:NAME_LENand :OTHER_LEN,因为我可能会更改参数的顺序或添加新的参数,并且我想保持明确的绑定。

现在,对于问题:我的 prepare 不返回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

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

4

1 回答 1

0

为了不回答您的问题,sqlite 没有严格的文本列大小。为了兼容性,它接受 VARCHAR 类型,但其行为没有变化。

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

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

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

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

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 );

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

于 2012-01-24T21:38:32.230 回答