2

我正在使用 MySQL 连接器/网络,我想针对将在运行时指定名称的表编写查询。

这个例子不在我的脑海中(未经测试):

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 注入的可能性。

这看起来是个好方法吗?有没有更好的办法?

4

3 回答 3

4

您不能在 MySQL 中参数化标识符(表名或字段名),但是,您可以使用反引号对它们进行转义。

以下查询将安全运行,但会产生错误,因为该表不存在(除非出于某种奇怪的机会,您实际上有一个这样命名的表):

SELECT * FROM `users; DROP TABLE users;`;

基本上,您可以使用动态名称或字段,只要它们包含在反引号中即可。为了以这种方式防止 SQL 注入,您需要做的就是首先去除所有反引号:

tableName = tableName.Replace("`", "");
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";
于 2010-01-15T19:21:33.597 回答
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
于 2010-01-15T19:22:31.220 回答
1

对,您不能将查询参数用于表名、列名、SQL 关键字或表达式等。您只能将查询参数用于单个值。

我同意从输入到文字表名的某种映射是防止 SQL 注入的好方法。

我不使用 .NET 进行编程,我通常使用 PHP、Python 或 Perl 等动态语言。所以我使用哈希数组。switch()如果您可以简单地使用枚举变量来索引散列数组,则可以跳过。

$tableName = $tableNameHash[ $table ];

.NET 是否支持散列映射类型的数据结构?这就是我要寻找的。


看起来hash_map标准 C++ 库中有一个类。

于 2010-01-15T19:19:27.097 回答