2014-05-05 81 views
0

我在SQLite中遇到了一些麻煩。我曾經將「時間」保存爲一個整數,但是現在我想將其作爲一個雙精度值,這導致了一些問題。每當我嘗試新的修補程序時,我都會重新制作數據庫,但它沒有任何作用。每當我嘗試保存時,都會收到錯誤「3列4個值」。當我把它全部改回到int時,它再次正常工作。另外,如果我只是從保存過程中刪除了「time all togeater」,那麼我得到的錯誤是「3列的2個值」。我不知道發生了什麼。真的會佔用兩個值還是什麼?SQLite REAL錯誤

創建表:

  sql = "CREATE TABLE Speed (id INTEGER PRIMARY KEY AUTOINCREMENT, LanguageType VARCHAR(20), cardsetNumber INT, time REAL)"; 
     command = new SQLiteCommand(sql, dbConnection); 
     command.ExecuteNonQuery(); 

添加到表:

public void SaveSpeed(int cardsetNumber, LanguageType lt, double time) 
    { 
     Open(); 
     sql = "insert into Speed (cardsetNumber, LanguageType, time) values (" + cardsetNumber + ", '" + lt + "', " + time + ")"; 
     command = new SQLiteCommand(sql, dbConnection); 
     command.ExecuteNonQuery(); 
     Close(); 
    } 
+0

你的語言環境是什麼?你可以在每種情況下輸出sql的內容嗎?我懷疑你的語言環境使用'''作爲小數點分隔符,並且'double'的值被渲染成類似'0,0'的形式,然後在SQL表達式中將其解釋爲* 2 *值。 –

+0

一旦您確認了我的懷疑,*請*永遠不要通過字符串連接將值插入到SQL字符串中;使用[參數](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue%28v=vs.110%29.aspx)。 –

+0

我來自丹麥,如果這涵蓋了你的問題。有沒有辦法解決? – user3026046

回答

1

Wikipedia,丹麥使用逗號作爲小數點分隔最可能的是,你的進程默認的文化是丹麥一個在轉換時強制使用小數點分隔符十進制數字到字符串。

你是做兩件事情,你不應該在你的代碼做,但在這種情況下,改變一個將解決這個問題:

  • 您的值轉換爲基於文化的一個字符串,除了將其顯示給用戶之外,其他目的不是invariant culture
  • 您正在構建一個帶有自定義值的SQL查詢,方法是將未轉義的值連接到查詢字符串中。

第一種意思是,不希望讀取特定於語言環境的數字格式的代碼將簡單地解釋您的字符串與預期不同。特別是,在另一臺機器(具有另一個缺省語言環境集)讀取字符串時,這是正確的,但在這種情況下,這僅僅是因爲SQL解析器從不期望任何特定於語言環境的數字格式(並且,作爲參數分隔符,語法實際上會停止被很好地定義,除非解析器將添加任何進一步的區域特定修改)。

第二個可能會導致really bad trouble,所以你總是避免它。


那麼,這裏發生了什麼?與該特定語言環境轉換,時間數字轉換爲類似1,2-,通過SQL分析器解釋爲整數(用逗號分開),而不是作爲一個十進制數。因此有關參數計數的錯誤消息。


第一個問題可以通過顯式指定字符串轉換不變的文化時,結果是針對方案,而不是人來解決。 總是會在您或其他人打算將值讀回數字類型時執行此操作,例如,當以CSV或XML等計算機的基於文本的格式存儲該值時。

至於第二個問題,要將任何自定義(文字)值插入到您的SQL查詢(特別是,但不是排他性的,那些沒有硬編碼的地方,但從用戶輸入接收),參數化您的查詢字符串:

sql = "insert into Speed (cardsetNumber, LanguageType, time) values (@cardsetNumber, @lt, @time)"; 
command = new SQLiteCommand(sql, dbConnection); 
command.Parameters.AddWithValue("@cardsetNumber", cardsetNumber); 
command.Parameters.AddWithValue("@lt", lt); 
command.Parameters.AddWithValue("@time", time); 

這將自動插入任何報價或逃避引號的字面值,並且不存在有意或無意SQL injection風險。

+1

這對我有很大的幫助,謝謝你的迴應! – user3026046