2010-06-24 66 views
1

很好,問題是清楚的,我希望,代碼是這樣的:我迷路了:這個ado.net代碼有什麼問題?

string sql = "delete from @tabelnaam"; 
      SqlCommand sc = new SqlCommand(); 

       sc.Connection = getConnection(); 
       sc.CommandType = CommandType.Text; 
       sc.CommandText = sql; 
       SqlParameter param = new SqlParameter(); 

       param.Direction = ParameterDirection.Input; 
       param.ParameterName = "@tabelnaam"; 
       param.Value = tableName; 

       sc.Parameters.Add(param); 
       OpenConnection(sc); 
       sc.ExecuteScalar(); 

tablename是提供給該函數。

我得到異常:

Must declare the table variable @tabelnaam 

回答

1

做出改變

,而不是使用放慢參數使用本

string sql = string.format("delete from {0}",tableName); 

化妝用的ExecuteScalar

sc.ExecuteNonQuery(); 
+0

是不是會導致sql注入? – Michel 2010-06-24 11:15:15

+0

你可以通過驗證表名正確來避免這種情況 – 2010-06-24 11:37:42

3

IIRC,你不能使用替換表名的參數。

而是生成包含正確表名的SQL字符串。

+0

是不是導致sql注入? – Michel 2010-06-24 11:12:37

+0

@Michel:你如何得出這個結論? – leppie 2010-06-24 11:20:02

+2

當然,如果字符串的來源是通過不受信任的來源(如用戶輸入),那麼它是sql注入的風險。如果我輸入以下「表名」:「MyTable; DROP DATABASE MyDb」。 – 2010-06-24 11:31:38

0

的的ExecuteNonQuery這一翻譯的我不認爲你可以參數表名。從我讀過的,你可以通過動態sql和調用sp_ExecuteSQL來完成。

+0

呵呵?所以我可以這樣做'select * from client where name = @name'但我不能這樣做:'從@table'刪除? – Michel 2010-06-24 11:16:58

+1

@michel - 確切地說。 – 2010-06-24 11:33:41

+0

[吃驚]感謝評論 – Michel 2010-06-28 09:27:19

0

您的SQL不正確,您正在從表變量中刪除,但尚未定義該變量。

更新:正如有人指出的那樣,您嘗試動態構建查詢字符串,但卻使用了無意使用的SQL參數(這些參數不能用作字符串文本的佔位符)。

+0

感謝您的編輯,沒有發現:) – 2010-06-24 10:51:52

+0

我不知道我知道你的意思。 – Michel 2010-06-24 11:14:40

+0

您使用的@tableName語法後跟comm.Parameters集合,爲您提供了一個名爲「參數化SQL」的內容。該命令試圖將「value」放入@tableName中,而不是您想要的字符串文字。您只是想使用字符串構建一個沒有任何參數的SQL塊。 – 2010-06-24 11:23:46

1

正如其他人所提到的,你不能參數化的表名。

然而,正如你正確地提到在其他答案的評論,使用簡單的字符串操作potentialy介紹了SQL注入風險:

如果你的表名輸入來回不可信的來源,比如用戶輸入,然後使用該:

string sql = string.format("DELETE FROM {0}",tableName); 

離開你 「myTable的; DROP DATABASE MYDB」 表名打開插入,給你:

DELETE FROM myDb; DROP DATABASE MyDB 

的方式RO UND這是界定表名做,因爲這一些諸如:在組合

string sql = string.format("DELETE FROM dbo.[{0}]", tableName); 

檢查該輸入不包含任一「[」或「]」;你應該檢查它也不包含任何不能用作表名的其他字符,例如句點和引號。

+0

你的意思是'dbo.'不是'do.'?不過,表格可以存在於其他模式中。 – Rup 2010-06-24 11:41:37

+0

@Rup - 我做到了 - 很好,謝謝。確實,他們可以生活在其他模式中。我只是想在OP上留下一個想法,讓事物儘可能地受到限制*。如果這些表格在其他模式中,那麼這將需要放鬆,但是*只有在這種情況下。 – 2010-06-24 11:44:53

0

你不能參數化表名,你必須將它注入命令文本。

,你可以和應該做的是保護自己免受SQL注入通過這樣界定的名字:

public static string Delimit(string name) { 
    return "[" + name.Replace("]", "]]") + "]"; 
} 

// Construct the command... 
sc.CommandType = CommandType.Text; 
sc.CommandText = "delete from " + Delimit(tableName); 
sc.ExecuteNonQuery(); 

更多的背景資料見herehere