代码之家  ›  专栏  ›  技术社区  ›  Andy West

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

  •  2
  • Andy West  · 技术社区  · 15 年前

    我使用的是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 回复  |  直到 15 年前
        1
  •  4
  •   zombat    15 年前

    你不能对一个 identifier 但是,在MySQL中,您可以使用反勾号来转义它们。

    以下查询将安全运行,但会产生错误,因为该表不存在(除非您有一个这样的表,这很奇怪):

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

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

    tableName = tableName.Replace("`", "");
    string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";
    
        2
  •  2
  •   Quassnoi    15 年前

    动态表名从来都不是一个好方法(除非您正在开发 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
    
        3
  •  1
  •   Bill Karwin    15 年前

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

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

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

    $tableName = $tableNameHash[ $table ];
    

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


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