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

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

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

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

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

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

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
10
0
7 989
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

create procedure myProc

@tableName nvarchar(50)

as

sp_executesql N'select * from ' + @tablename

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

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

Будет 'выбрать * из' + @tablename. Тогда быть параметризованным? (с использованием кода VB.Net, а не хранимых процедур).

Damien 17.12.2008 12:00

Если вы создадите запрос в vb.net, тогда никакие @table не нужно будет параметризировать. Ваш код vb будет выглядеть так: sqlString = "select * from" + tableName. Затем вы должны выполнить sqlString, используя объект команды. (установить тип команды на текст)

JoshBerke 17.12.2008 17:11

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

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

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

Ответ принят как подходящий

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

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

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

Да, исходный код и только в исходном коде. Это сделано для того, чтобы упростить работу по созданию операторов обновления / вставки, пока я реорганизую эту вещь.

Damien 17.12.2008 12:02

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

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

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

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

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

dr. evil 16.12.2008 21:18

Что ж, у людей в компании тоже не будет доступа. Только вызывающий метод сможет указать имена полей и таблиц. На самом деле, любой, у кого есть доступ к бизнес-логике, в любом случае будет иметь доступ к коду доступа к данным,

Damien 17.12.2008 11:57

Пожалуйста, посмотрите этот пост-ответ пользователя Vimvq1987: MySqlParameter как TableName

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

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

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

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

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

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

Другие вопросы по теме