Имя таблицы параметров в .NET / SQL?

Как следует из темы, я хочу иметь возможность передавать имена таблиц в качестве параметров с помощью .NET (неважно, какой язык на самом деле) и SQL Server.

Я знаю, как это сделать для значений, например command.Parameters.AddWithValue("whatever", whatever) с использованием @whatever в запросе для обозначения параметра. Дело в том, что я нахожусь в ситуации, когда я хочу иметь возможность делать это с другими частями запроса, такими как имена столбцов и таблиц.

Это не идеальная ситуация, но я должен ее использовать, на самом деле она не подвержена SQL-инъекции, поскольку только кто-то, использующий код, может установить эти имена таблиц, а не конечный пользователь. Однако это грязно.

Итак, возможно ли то, о чем я спрашиваю?

РЕДАКТИРОВАТЬ: Чтобы прояснить вопрос о SQL-инъекции, имена таблиц передаются только исходным кодом, в зависимости от ситуации. Это указывает разработчик. У разработчика в любом случае будет доступ к уровню базы данных, поэтому я спрашиваю не столько о безопасности, сколько о том, чтобы сделать код чище.


person Damien    schedule 16.12.2008    source источник


Ответы (7)


Я не думаю, что я когда-либо встречал эту возможность ни в одном из диалектов SQL, но это не область знаний.

Я бы предложил ограничить символы до AZ, az, 0-9, '.', '_' И '' - а затем использовать любые подходящие скобки для базы данных (например, [] для SQL Server, я полагаю), чтобы обернуть вокруг всего этого. Затем просто поместите его прямо в SQL.

Не совсем понятно, что вы имели в виду, говоря, что это не риск внедрения SQL-кода - вы имеете в виду, что имена будут в исходном коде и только в исходном коде? Если так, то я согласен, что это улучшит ситуацию. Возможно, вам даже не потребуется делать брекетинг автоматически, если вы уверены, что ваши разработчики не кретины (намеренно или нет).

person Jon Skeet    schedule 16.12.2008
comment
Да, исходный код и только в исходном коде. Это сделано для того, чтобы упростить работу по созданию операторов обновления / вставки, пока я реорганизую эту штуку. - person Damien; 17.12.2008

Вы не можете напрямую параметризовать имя таблицы. Вы можете сделать это косвенно через sp_ExecuteSQL, но вы также можете создать (параметризованный) TSQL на C # (объединяя имя таблицы, но не другие значения) и отправить его как команду. Вы получаете ту же модель безопасности (т.е. вам нужен явный SELECT и т. Д., При условии, что он не подписан и т. Д.).

Также - обязательно занесите имя таблицы в белый список.

person Marc Gravell    schedule 16.12.2008

Вы можете передать имя таблицы в качестве параметра, как и любой другой параметр. Ключ в том, что вам нужно создать динамический оператор sql, который затем следует рассмотреть, проще ли его создать на уровне вашего приложения или в процессах.

create procedure myProc

@tableName nvarchar(50)

as

sp_executesql N'select * from ' + @tablename

fyi, этот образец кода взят из памяти, посмотрите на BOL, чтобы узнать правильный синтаксис sp_executesql.

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

person JoshBerke    schedule 16.12.2008
comment
Будет 'выбрать * из' + @tablename. Тогда быть параметризованным? (с использованием кода VB.Net, а не хранимых процедур). - person Damien; 17.12.2008
comment
Если вы создаете запрос в vb.net, тогда никакие @table не нужно параметризировать. Ваш код vb будет выглядеть так: sqlString = select * from + tableName. Затем вы должны выполнить sqlString, используя объект команды. (установить тип команды на текст) - person JoshBerke; 17.12.2008

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

Единственный способ сделать имя таблицы динамическим - это интерполировать переменную в ваш SQL-запрос до того, как вы подготовите эту строку как инструкцию.

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

person Bill Karwin    schedule 16.12.2008

Идея о том, что он не подвержен SQL-инъекциям, ошибочна. Он может быть менее подвержен SQL-инъекциям со стороны внешних пользователей, но по-прежнему очень подвержен SQL-инъекциям. Большинство атак на базы данных происходят изнутри атакуемой компании, а не от конечных пользователей.

У сотрудников может быть недовольство, они могут быть нечестными, они могут быть недовольны или просто не столь умны и думать, что можно обойти систему безопасности, чтобы делать то, что, по мнению ОНИ, должно быть сделано. база данных.

person Tom H    schedule 16.12.2008
comment
Я собирался сказать это, просто проголосовал вместо этого. Если параметр не является жестко запрограммированным, это плохая идея. - person dr. evil; 16.12.2008
comment
Что ж, у людей в компании тоже не будет доступа. Только вызывающий метод сможет указать имена полей и таблиц. На самом деле, любой, у кого есть доступ к бизнес-логике, в любом случае будет иметь доступ к коду доступа к данным, - person Damien; 17.12.2008

См. Этот пост-ответ пользователя Vimvq1987: MySqlParameter as TableName

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

Перефразируя основную идею:

    SELECT table_name
    FROM information_schema.tables
    WHERE table_schema = 'databasename'
    AND table_name = @table;

    cmd.Parameters.AddWithValue("@table",TableName);

Если это возвращает нормально с именем таблицы, продолжайте свой основной запрос ...

person trevor hughes    schedule 11.07.2013

Я бы просто проверил select OBJECT_ID(@tablename), идея состоит в том, чтобы предотвратить инъекцию, вы знаете, что это должно быть имя таблицы, это было, если это возвращает число, тогда я бы запустил фактический запрос,

person drewex    schedule 27.02.2015