2011-02-03 2 views
2

Я пытаюсь создать параметризованный запрос в C# для базы данных SQL-сервера.Можете ли вы использовать SQLParameter в инструкции SQL FROM?

Код:..

 query = new StringBuilder("SELECT @fields FROM @tables"); 

     using(SqlConnection connection = new SqlConnection(connection)) 
     { 
      SqlCommand command = new SqlCommand(query.ToString(), connection); 
      command.Parameters.AddWithValue("@fields", fields.ToString()); 
      command.Parameters.AddWithValue("@tables", tables.ToString()); 

      try 
      { 
       connection.Open(); 
       Int32 rowsAffected = command.ExecuteNonQuery(); 
       Console.WriteLine("RowsAffected: {0}", rowsAffected); 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 

Странная часть этого терпит неудачу с сообщением «Необходимо объявить переменную таблицы \» @ таблиц \»Тем не менее, как вы можете видеть, это четко определено

Так что мой вопрос:

  1. вы можете передать параметр, чтобы определить список таблиц в ОТ состояния Мент?
  2. Если вы можете, почему нет это работает?
+1

В качестве побочного примечания к этим ответам о динамическом SQL. Всегда, всегда, всегда будьте очень осторожны при построении динамического SQL, чтобы избежать инъекции SQL. Когда вы строите SQL на лету, вы открываете себя, поэтому убедитесь, что вы проверяете его либо в своем приложении, либо в самом скрипте SQL. –

+0

@Joe Именно поэтому я пытаюсь параметризовать столько, сколько могу. Предложение Where также будет полностью управляться параметрами - добавьте к этому тот факт, что пользовательский интерфейс не имеет текстовых полей, только флажки и многосегментные списки, я должен быть довольно хорошо охвачен. – morganpdx

+1

Вы не можете доверять select-box input. Злоумышленнику очень просто запускать javascript в форме, которая изменяет значения там, или просто публиковать форму вручную со значениями, которые они хотят, а не тем, что ваша форма должна ограничивать вас. (Предполагается, что это веб-приложение, но эта же концепция применяется, совсем немного иначе, к приложениям Windows). Поэтому убедитесь, что у вас есть еще один уровень защиты в коде сервера. –

ответ

6

SQL не поддерживает предложение FROM для параметризации. Таким образом, вам нужно использовать динамический SQL или создать/объединить строку запроса перед отправкой в ​​базу данных.

+0

Следите за внедрением SQL, если вы идете по этому маршруту. –

+0

@Abe Miessler: Именно поэтому предложение FROM не поддерживает замену. –

+0

Действительно? Почему он работает для параметров, но не для имен таблиц? Связано: http: // stackoverflow.com/questions/4892166/how-do-sqlparameter-prevent-sql-injection –

2

Нет, к сожалению, вы не можете использовать параметр в предложении FROM.

1

Я думаю, что это не так, как должна выглядеть команда SQL и ее параметры. Он должен выглядеть так:

SELECT fieldName1, fieldName2 
FROM TableName 
WHERE fieldName = @paramName 

Вы не можете использовать параметры в качестве определения полей, которые нужно выбрать, или целевой таблицы. Если вам нужно определить поля, которые нужно выбрать, просто составьте командную строку в StringBuilder, прежде чем вы ее вызовите - по мере необходимости. Параметры используются для целей фильтрации. В вашем случае вам не нужны никакие параметры, просто создайте свою команду и выполните.

+1

+1: Ваше предположение правильно, но [чтобы мы не забыли Little Bobby Tables] (http://xkcd.com/327/) –

0

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

Это только для иллюстрации - для реальной жизни, очевидно, вы должны были бы сделать это намного ровнее:

declare @TABLE_NAME nvarchar(128) 
set @TABLE_NAME = 'Robert'');DROP TABLE Students;--' -- This line will raise an error 
set @TABLE_NAME = 'BOOK' -- This line will go through properly 

declare @sql varchar(max) 
set @sql = 'SELECT * FROM ' 

if exists (select 1 from sys.objects where type = 'U' and name = @TABLE_NAME) 
    begin 
     set @sql = @sql + @TABLE_NAME 
     exec (@sql) 
    end 
else 
    begin 
     raiserror ('ERROR ERROR ERROR', 0, 0) 
     return 
    end 
Смежные вопросы