2010-06-24 40 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