Каков наилучший способ динамического выбора имени таблицы во время выполнения? - PullRequest
2 голосов
/ 15 января 2010

Я использую 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-инъекции .

Это похоже на хороший подход? Есть ли лучший способ?

Ответы [ 3 ]

4 голосов
/ 15 января 2010

Вы не можете параметризировать идентификатор (имя таблицы или имя поля) в MySQL, однако вы можете избежать их, используя обратные метки.

Следующий запрос будет выполнен безопасно, но выдаст ошибку, потому что таблица не существует (если только по какой-то странной случайности у вас на самом деле нет таблицы с таким именем):

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

По сути, вы можете использовать динамические имена или поля, если они заключены в обратные кавычки. Чтобы предотвратить внедрение SQL таким способом, все, что вам нужно сделать, это сначала убрать любые обратные пометки:

tableName = tableName.Replace("`", "");
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`";
2 голосов
/ 15 января 2010

Имена динамических таблиц никогда не подходят (если вы не разрабатываете 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
1 голос
/ 15 января 2010

Правильно, нельзя использовать параметр запроса для имени таблицы, имени столбца, ключевого слова или выражения SQL и т. Д. Вы можете использовать параметр запроса только для одного значения.

Я согласен с тем, что выполнение какого-либо отображения от ввода до буквального имени таблицы является хорошим способом защиты от внедрения SQL.

Я не программирую на .NET, я обычно использую динамические языки, такие как PHP, Python или Perl. Поэтому я использую хэш-массив. Вы можете пропустить switch(), если можете просто использовать переменную перечисления для индексации в хеш-массив.

$tableName = $tableNameHash[ $table ];

Поддерживает ли .NET структуру данных типа хэш-карты? Это то, что я искал.


Похоже, что в стандартной библиотеке C ++ есть класс hash_map.

...