2016-12-14 48 views
-1

我正在向服務器發送消息並將消息上傳到數據庫中,大多數單詞都正確地通過,但我注意到當我發送單詞 「這是怎麼回事? 「它給出了一個錯誤,但是當我發送「whats up?」時T和S之間沒有單個逗號,它很好。在字符串中使用單引號時出現奇怪的SQL異常

什麼問題?

這是我得到的異常: 附加信息:'s'附近的語法錯誤。

字符串')'後面未加上引號。

我在com.Executenonquery行得到異常。

string message = bf.Deserialize(client).ToString(); 
SqlCommand com = new SqlCommand($"insert into messages (messagetext,sentdate) values ('{message}','{DateTime.Now}')",sc); 
int success = com.ExecuteNonQuery(); 
if (success < 1) 
{ 
    MessageBox.Show("Something went wrong"); 
} 
+13

使用參數!不要直接輸入查詢字符串。您剛剛瞭解了SQL注入。只需谷歌,並瞭解更多關於它。 –

+0

除了爲SQL注入提供保護外,還允許一些性能改進,以及更多,使用查詢中的參數,因爲@GordonLinoff建議可以幫助您很多:日期格式化,字符串內部等等,沒有問題... –

回答

2
string message = bf.Deserialize(client).ToString(); 
SqlCommand com = new SqlCommand("insert into messages (messagetext,sentdate) values (@sqlMessage, @sqlDatetime)", sc); 
com.Parameters.AddWithValue("@sqlMessage", message); 
DateTime myDateTime = DateTime.Now; 
var sqlFormattedDate = myDateTime.ToString("yyyy-MM-dd HH:mm:ss"); 
com.Parameters.AddWithValue("@sqlDataTime", sqlFormattedDate); 

int success = com.ExecuteNonQuery(); 
if (success < 1) 
{ 
    MessageBox.Show("Something went wrong"); 
} 

添加參數將解決您的問題,您要添加的字符串作爲'hello'而不是hello例如

+0

附註。 ToString(「yyyy-MM-dd HH:mm:ss」)格式在每個日期和語言設置下都不可靠(特別是如果版本信息未知)。更好的格式是ToString(「yyyyMMdd HH:mm:ss」),更好的是讓Date/DateTime或DateTime2類型的參數讓驅動程序處理。 –

1

您需要將單引號加倍才能工作,但應該使用參數化查詢。系統將爲您處理所有事情,並檢查變量的內容以防止SQL腳本注入。

+0

我提高了你的建議,但是稍作修改。系統不會檢查變量的內容。你傳遞的東西是純文本,它會按原樣存儲(不執行 - 它也可以包含任何腳本)。 –

1

因爲你的投入產生像下面一個無效的查詢..

insert into messages (messagetext,sentdate) values ('what's up?','somedate') 

你觀察的區別?您的單引號關閉開頭的開頭引號,前面的單詞什麼。要解決此問題,使用參數化SQL始終是最佳做法。

下面是一些參考

SQL Injection

+0

我明白了,謝謝! – NateS

-1

它看起來就像你在C#編碼呢?

如果是這樣可能是因爲'是一個txt分隔符。我想你可以通過把你的轉義字符放在那裏來解決它。它可能是(?)\所以消息應該是「有什麼事」,因爲它在使用時不會在你的txt文件中出現異常。'

當你在SQL中拋出它時仍然會出錯,還有用於定義字符串中的開始/停止。要修復它,你需要設置雙'

等'什麼是'!'

+0

他的確在使用C#,但它與使用的客戶端語言無關。你應該簡單地使用參數。沒有一個開發人員真正將這些值編碼爲''而不是''。在這種情況下,它也是消息變量,它給出了一個簡單應該是參數的悲傷。如果他糾正了它,可能還需要處理日期時間值(這可能在沒有給出任何錯誤但存儲錯誤值的情況下工作 - 未被注意的錯誤比錯誤更糟糕)。 –

3

你在腳下射擊自己。

您的字符串:

$"insert into messages (messagetext,sentdate) values ('{message}','{DateTime.Now}')" 

傳遞後 「什麼事?」你得到:

insert into messages (messagetext,sentdate) values ('what's up?','...') 

看到這個零件:'what's up?'?撇號也是SQL中字符串的引用。這就是您應該的原因切勿使用字符串操作在SQL中放入數據。使用參數或更好的ORM。

+0

我認爲主要原因是防止SQL注入。 – jarlh

+0

@jarlh井OP只是SQL注入自己。 – Andrey

0

原因是使用的是單'(單引號),而不是雙和充當字符串文字的結尾,導致SQL無效。您應該使用參數:

  1. 避免SQL注入攻擊。
  2. 避免像剛剛遇到的問題和更多(如正確格式化和傳遞日期\日期時間值)。

此外,在你的代碼檢查結果值是沒用的,因爲你會得到一個異常。修正的代碼:

int rows = 0; 
string message = bf.Deserialize(client).ToString(); 
SqlCommand com = new SqlCommand(@"insert into messages 
    (messagetext,sentdate) 
    values 
    (@message, @sent)", sc); 
com.Parameters.Add("@message",SqlDbType.VarChar).Value = message; 
com.Parameters.Add("@sent",SqlDbType.DateTime2).Value=DateTime.Now; 
try 
{   
    sc.Open(); 
    rows = com.ExecuteNonQuery(); 
    sc.Close(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show("Something went wrong:"+ex.Message); 
} 
if (rows < 1) // this should never happen without an exception - redundant 
{ 
    MessageBox.Show("Something went wrong - no rows were inserted"); 
} 
0

正如其他人說的... 這個問題有幾個選項。您可以使用SqlCommand的AddParameterWithValue方法。

  1. 選項加入參數; (MessageText,senddate)values(@MesasgeText,@SentDate)「 var messageText = bf.Deserialize(client).ToString(); System.Data.SqlClient.SqlCommand scmd = new System.Data.SqlClient.SqlCommand(sqlString); scmd.Parameters.AddWithValue(「@ MesasgeText」,messageText); scmd.Parameters.AddWithValue(「@ SentDate」,DateTime.Now);

  2. 選擇與編碼/解碼=>如果您將使用此選項不要忘記HtmlDecode當您將顯示messageText到最終用戶在網站上。

    var messageText = HttpUtility.HtmlEncode(bf.Deserialize(client).ToString());

希望這可以幫到你, 親切的問候。

相關問題