我的sqlite数据库有一个奇怪的或者可能不那么奇怪的问题。我有一个“文本”类型的字段,它的作用就像任何英文文本的魅力一样。
以前的字段中的文本来自MFC CEdit。现在我切换到CRichEditCtrl以支持格式化和UNICODE文本。 CRichEditCtrl以十六进制形式转储格式化文本,如:{\ rtf1 \ ansi \ ansicpg1252 \ deff0 \ deflang1033 {\ fonttbl {\ f0 \ fnil \ fcharset0 MS Shell Dlg 2;}}等。
再一次,sqlite大部分时间都可以保存它。但有一段时间它没有给出错误代码SQLITE_ERROR / * SQL错误或缺少数据库* /。这条消息不太有帮助。数据库存在并保存大部分时间????去搞清楚。 这是代码:
error = sqlite3_exec(db,cmd,0,0,0);
if (error != SQLITE_OK){
errMsg.Format("Unable to save notes to: %s\nSQLite Error: %d",filename,error);
AfxMessageBox(_T(errMsg));
sqlite3_close(db);
return false;
}
我认为没有什么不寻常的。
如果您有任何想法,请告诉我。可能是由于RTF格式中的大量反斜杠,它会以某种方式混淆sqlite?哦,它与保存的文本大小无关。 非常感谢。 瓦尔
答案 0 :(得分:2)
问题肯定是因为你的代码中没有转义特殊字符。我建议您使用sqlite API来准备语句,以避免大量的字符串处理麻烦。他们会为您插入值并自动处理转义。
而不是:
error = sqlite3_exec(db,cmd,0,0,0);
你需要这样做:
sqlite3_stmt *stmt;
error = sqlite3_prepare_v2(database, "INSERT INTO table (field) VALUES (?)", -1, &stmt, NULL);
if (error != SQLITE_OK) { ...
error = sqlite3_bind_text(stmt, 1, rtfString, -1, SQLITE_STATIC);
if (error != SQLITE_OK) { ...
error = sqlite3_step(stmt);
if (error != SQLITE_DONE) { ...
sqlite3_finalize(stmt);
sqlite将自动获取rtfString
的值,正确引用,然后将其插入查询中代替问号。
这种方式的另一个好处是可以重用stmt
对象。每次使用后只需致电sqlite3_reset()
,并记得在完成任务后致电sqlite3_finalize()
。
答案 1 :(得分:1)
如果一个反斜杠有效,那么应该有几个。但是,如果文本包含撇号或双引号,则可能无法正确转义文本,这会破坏查询。
如果你没有逃避报价,那么这可能就是问题所在。假设你先做引号,比如
{blabla\'somethingelse}
然后再次转义该字符串以保留反斜杠(否则它们将在与数据库的通信中丢失),这将产生
{blabla\\'somethingelse}
然后瞧,你松散的撇号......
解决方案是首先转义反斜杠,然后是撇号和引号。