Как параметризовать имя таблицы в запросе ODBC

#c# #odbc #informix #parameterized-query

#c# #asp.net #sql-сервер #odbc

Вопрос:

У меня есть подключение ODBC к базе данных, и я хотел бы, чтобы пользователь мог просматривать данные в любой таблице. Поскольку это ASP.net приложение Я не могу быть уверен, что отправленное имя таблицы также не содержит неприятностей. Я пытался использовать параметризованный запрос, но я всегда получаю сообщение об ошибке, в котором говорится, что я «Должен объявить переменную таблицы» — это кажется проблемой, потому что это имя таблицы

  string sql = "SELECT TOP 10 * FROM ? ";
 OdbcCommand command = new OdbcCommand(sql, dbConnection);
 command.Parameters.Add(new OdbcParameter("@table", tableName));
 OdbcDataAdapter adapter = new OdbcDataAdapter();
 adapter.SelectCommand = command;
 adapter.Fill(tableData);
  

Каков наилучший способ добиться этого безопасным способом?

Ответ №1:

Используйте хранимую процедуру, это самый безопасный способ.

Некоторые подсказки:

  1. Вероятно, вы также можете использовать объекты System.Data.SqlClient пространства имен
  2. Заключите инициализации ваших объектов connection, command и adapter в using инструкции

Вот простой пример:

 string sqlStoredProcedure = "SelectFromTable";
using (OdbcConnection dbConnection = new OdbcConnection(dbConnectionString))
{
    dbConnection.Open();
    using (OdbcCommand command = new OdbcCommand(sqlStoredProcedure, dbConnection))
    {
        command.CommandType = System.Data.CommandType.StoredProcedure;
        command.Parameters.Add(new OdbcParameter("@table", tableName));
        using (OdbcDataAdapter adapter = new OdbcDataAdapter(command))
        {
            adapter.SelectCommand = command;
            adapter.Fill(tableData);
        }
    }
}
  

Другим способом было бы получить все имена таблиц и проверить tableName строковую переменную как запись в списке, возможно, используя:

 DataTable tables = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables);
  

Вот простая реализация, основанная на вашем сценарии:

 string sql = "SELECT TOP 10 * FROM {0}";
using (OdbcConnection dbConnection = new OdbcConnection(dbConnectionString))
{
    dbConnection.Open();

    DataTable tables = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables);
    var matches = tables.Select(String.Format("TABLE_NAME = '{0}'", tableName));

    //check if table exists
    if (matches.Count() > 0)
    {
        using (OdbcCommand command = new OdbcCommand(String.Format(sql, tableName), dbConnection))
        {
            using (OdbcDataAdapter adapter = new OdbcDataAdapter(command))
            {
                adapter.SelectCommand = command;
                adapter.Fill(tableData);
            }
        }
    }
    else
    {
        //handle invalid value
    }
}
  

Комментарии:

1. Спасибо! Но, к сожалению, у меня нет доступа к базе данных для добавления таких вещей, как SP, поэтому мне нужно сделать все это в приложении. но это интересное решение. Кроме того, было бы что-то вроде этого troyhunt.com/2012/12/stored-procedures-and-orms-wont-save.html применить к вашему решению?

2. В указанной вами ссылке EXEC(@query) вызывается хранимая процедура SQL после создания динамического запроса с использованием @SearchTerm параметра. Итак, разработчики SQL также должны позаботиться о том, как они на самом деле используют данные и каковы риски динамических запросов.

3. Только что видел ваше редактирование, кажется, это самый простой способ сделать это, даже если он немного менее элегантный. Спасибо за вашу помощь!