What's the best way to choose a table name dynamically at runtime?

不问归期 提交于 2019-12-24 01:40:59

问题


I am using MySQL Connector/Net and I want to write a query against a table whose name will be specified at runtime.

This example is off the top of my head (not tested):

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...
    }
}

Since I don't think you can parameterize a table name in a query, I used an enum rather than a string in the function parameter to limit the possibility of SQL injection.

Does that seem like a good approach? Is there a better way?


回答1:


You can't paramaterize an identifier (table name or field name) in MySQL, however, you can escape them using backticks.

The following query will run safely but produce an error because the table doesn't exist (unless by some weird chance you actually have a table named like this):

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

Basically, you can use dynamic names or fields as long as they are enclosed in backticks. In order to prevent SQL injection this way, all you need to do is strip out any backticks first:

tableName = tableName.Replace("`", "");
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";



回答2:


Dynamic table names are never a good approach (unless you are developing a PHPMyAdmin or something similar).

If you table names are limited, why don't you just make a stored procedure and call it with a parameter?

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:


Right, you can't use a query parameter for a table name, a column name, an SQL keyword or expression, etc. You can use a query parameter only for a single value.

I do agree that doing some kind of mapping from input to the literal table name is a good way to protect against SQL injection.

I don't program in .NET, I usually use dynamic languages like PHP, Python, or Perl. So I use a hash array. You can skip the switch() if you can simply use your enumeration variable to index into the hash array.

$tableName = $tableNameHash[ $table ];

Does .NET support a hash-map type of data structure? That's what I'd look for.


Looks like there is a hash_map class in Standard C++ library.



来源:https://stackoverflow.com/questions/2074094/whats-the-best-way-to-choose-a-table-name-dynamically-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!