我正在开发一个C++ API,它使用自定义设计的插件,使用它们的API和特定的SQL语法与不同的数据库引擎进行交互.
目前,我正在尝试找到一种插入BLOB的方法,但由于它NULL
是C/C++中的终止字符,因此在构造INSERT INTO查询字符串时BLOB会被截断.到目前为止,我一直在努力
//... char* sql; void* blob; int len; //... blob = some_blob_already_in_memory; len = length_of_blob_already_known; sql = sqlite3_malloc(2*len+1); sql = sqlite3_mprintf("INSERT INTO table VALUES (%Q)", (char*)blob); //...
我希望,如果它可以在SQLite3交互式控制台中完成,那么应该可以使用正确转义的NULL
字符构造查询字符串.也许有一种方法可以使用SQLite SQL语法支持的标准SQL来实现这一点?
当然有人必须面对同样的情况.我用Google搜索并找到了一些答案,但是还有其他编程语言(Python).
提前感谢您的反馈.
再次感谢大家的反馈.这次我在报告如何借助此处提供的指示解决问题.希望这将有助于其他人.
正如前三张海报所建议的那样,我确实使用了预处理语句 - 另外因为我也对获取列的数据类型感兴趣,而一个简单的sqlite3_get_table()
做法也没有.
以下面的常量字符串形式准备SQL语句之后:
INSERT INTO table VALUES(?,?,?,?);
它仍然是相应值的绑定.这是通过发出sqlite3_bind_blob()
与列一样多的调用来完成的.(我还使用sqlite3_bind_text()
了其他"简单"数据类型,因为我正在使用的API可以将整数/双精度/等转换为字符串).所以:
void* blobvalue[4]; int blobsize[4]; char *tail, *sql="INSERT INTO table VALUES(?,?,?,?)"; sqlite3_stmt *stmt=0; sqlite3 *db; /* ... */ db=sqlite3_open("sqlite.db"); sqlite3_prepare_v2(db, sql, strlen(sql)+1, &stmt, &tail); for(int i=0; i<4; i++) sqlite3_ bind_ blob(stmt, i+1, blobvalue[i], blobsize[i], SQLITE_TRANSIENT); if(sqlite3_step(stmt)!=SQLITE_DONE) printf("Error message: %s\n", sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close(db);
另请注意,某些函数(sqlite3_open_v2()
,sqlite3_prepare_v2()
)出现在后面的SQLite版本上(我想3.5.x及更高版本).
您将希望将此函数与预准备语句一起使用.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
在C/C++中,处理字符串中NULL的标准方法是存储字符串的开头和长度,或者存储指向字符串开头的指针和存储指向字符串末尾的指针.