Question

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?

Was it helpful?

Solution

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 + "`";

OTHER TIPS

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top