2012-11-07 72 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