在运行时动态选择表名的最佳方法是什么?

时间:2010-01-15 19:12:55

标签: .net mysql sql-injection parameterized

我正在使用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的可能性。

这看起来像是一种好方法吗?还有更好的方法吗?

3 个答案:

答案 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类。