我正在使用MySQL Connector / Net,我想针对一个名称将在运行时指定的表编写查询。
这个例子不在我的脑海中(未经测试):
public class DataAccess
{
public enum LookupTable
{
Table1,
Table2,
Table3
}
public int GetLookupTableRowCount(LookupTable table)
{
string tableName = string.Empty;
switch (table)
{
case LookupTable.Table1:
tableName = "table_1";
break;
case LookupTable.Table2:
tableName = "table_2";
break;
case LookupTable.Table3:
tableName = "table_3";
break;
default:
throw new ApplicationException("Invalid lookup table specified.");
}
string commandText = string.Concat("SELECT COUNT(*) FROM ", tableName);
// Query gets executed and function returns a value here...
}
}
由于我认为你不能在查询中参数化表名,我在函数参数中使用枚举而不是字符串来限制SQL injection的可能性。
这看起来像是一种好方法吗?还有更好的方法吗?
答案 0 :(得分:4)
你不能在MySQL中对identifier(表名或字段名)进行参数化,但是,你可以使用反引号来转义它们。
以下查询将安全运行但会产生错误,因为该表不存在(除非有一些奇怪的机会,您实际上有一个名为这样的表):
SELECT * FROM `users; DROP TABLE users;`;
基本上,您可以使用动态名称或字段,只要它们包含在反引号中。为了以这种方式防止SQL注入,您需要做的就是首先删除任何反引号:
tableName = tableName.Replace("`", "");
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";
答案 1 :(得分:2)
动态表名永远不是一个好方法(除非您正在开发PHPMyAdmin
或类似的东西)。
如果表名有限,为什么不用存储过程并用参数调用它?
DECLARE _which INT
BEGIN
SELECT COUNT(*)
FROM table_1
WHERE _which = 1
UNION ALL
SELECT COUNT(*)
FROM table_2
WHERE _which = 2
UNION ALL
SELECT COUNT(*)
FROM table_3
WHERE _which = 3
END
答案 2 :(得分:1)
是的,您不能对表名,列名,SQL关键字或表达式等使用查询参数。您只能将查询参数用于单个值。
我同意从输入到文字表名进行某种映射是防止SQL注入的好方法。
我不用.NET编程,我通常使用PHP,Python或Perl等动态语言。所以我使用哈希数组。如果您只是使用枚举变量来索引哈希数组,则可以跳过switch()
。
$tableName = $tableNameHash[ $table ];
.NET是否支持哈希映射类型的数据结构?这就是我想要的。
看起来标准C ++库中有一个hash_map
类。