问题
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