2012-11-07 39 views
3

我有一整套我想插入到表中的数据。我试图让它插入/更新一切或回滚。我打算在交易中这样做,但我不确定是否sql_exec()命令做了同样的事情。sqlite3交易和执行呼叫

我的目标是遍历列表。 根据主键选择每次迭代。

If result was found: 
    append update to string; 
else 
    append insert to string; 

然后通过迭代循环后,我将有一个巨大的字符串,并说:

sql_exec(串); sql_close(db);

是这样,应该怎样做呢?我打算在循环的每次迭代中都这样做,但是如果出现错误,我并不认为全局回滚。

+0

我会''sqlite3_exec()''BEGIN',然后单独执行每个更新。然后,您可以提交或回滚,具体取决于您是否衡量“成功”。 – Chad

+0

@Chad为什么是评论而不是答案? –

+0

@Fallenreaper哦,好的问题。 –

回答

5

不,你不应该把所有东西都附加到一个巨大的字符串中。如果你这样做了,你将需要为你分配一大堆内存,并且为每个单独的语句创建好的错误信息将会很困难,因为你只会得到整个字符串的单个错误。为什么要花费所有这些努力,在SQLite不得不再次将其解析为单个语句时构造一个大字符串?

相反,正如@Chad所建议的,您应该在BEGIN语句中使用sqlite3_exec(),该语句将开始一个事务。然后sqlite3_exec()反过来每条语句,最后sqlite3_exec()一个COMMITROLLBACK取决于一切如何。 BEGIN语句将启动一个事务,并且之后执行的所有语句都将在该事务中执行,并一起提交或回滚。这就是ACID代表的“A”;原子,因为事务中的所有语句将被提交或回滚,就好像它们是单个原子操作一样。

此外,你可能不应该,如果一些数据的每个语句内变化,如从文件中读取使用sqlite3_exec()。如果你这样做,一个错误可能很容易给你带来一个SQL injection错误。例如,如果你通过追加字符串来构造查询,并且你有像char *str = "it's a string"这样的字符串来插入,如果你没有正确引用它,你的陈述就会出现,如INSERT INTO table VALUES ('it's a string');,这将是一个错误。或者,如果有人恶意可以将数据写入此文件,那么他们可能会导致您执行他们想要的任何SQL语句(如果字符串为"'); DROP TABLE my_important_table; --",则为imagine)。您可能认为没有人会提供恶意输入,但如果有人将SQL解析器混淆成字符串,那么您仍然可能会有意外问题。

相反,你应该使用sqlite3_prepare_v2()sqlite3_bind_...()(其中...是类型,像intdoubletext)。为此,您使用char *query = "INSERT INTO table VALUES (?)"等语句,您可以用?替代您想要参数的位置,使用sqlite3_prepare_v2(db, query, -1, &stmt, NULL)进行准备,使用sqlite3_bind_text(stmt, 1, str, -1, SQLITE_STATIC)绑定参数,然后使用sqlite3_step(stmt)执行语句。如果语句返回任何数据,您将获得SQLITE_ROW,并且可以使用各种sqlite3_columne_...()函数访问数据。请务必仔细阅读文档;我给出的一些示例参数可能需要改变,具体取决于你如何使用它。

是的,与调用sqlite3_exec()相比,这有点多痛苦,但如果您的查询有任何从外部来源(文件,用户输入)加载的数据,这是正确执行此操作的唯一方法。 sqlite3_exec()是好的调用如果查询的整个文本包含源中,如BEGINCOMMITROLLBACK陈述,或没有零件从程序之外来预先写好的查询,你只需要准备/绑定,如果有任何意外的字符串可能会进入。

最后,您不需要查询数据库中是否已有某些内容,然后插入或更新它。您可以执行INSERT OR REPLACE查询,该查询可以插入记录,也可以用匹配主键替换,这相当于选择然后执行INSERTUPDATE,但更快更简单。有关更多详细信息,请参阅INSERT"on conflict"文档。

+1

有可能缺少部分答案,因为它似乎只是试图设置一个'if($ query =!empty){INSTERT} else {UPDATE}'的情况(即在php中;但是,标签指示C++)。无论如何,它可能需要编程或脚本语言。 –

+0

插入或替换会做我的if语句的工作,所以我不必建立语言特定的工具。感谢Brian的信息。 – Fallenreaper