Я новичок в работе с базами данных. Теперь я могу написать SELECT
, UPDATE
, DELETE
и INSERT
команду. Но я видел много форумов, где мы предпочитаем писать:
SELECT empSalary from employee where salary = @salary
...вместо того:
SELECT empSalary from employee where salary = txtSalary.Text
Почему мы всегда предпочитаем использовать параметры и как я могу их использовать?
Я хотел узнать об использовании и преимуществах первого метода. Я даже слышал о SQL-инъекциях, но не совсем понимаю. Я даже не знаю, связана ли SQL-инъекция с моим вопросом.
sql
sql-server
sql-injection
Сэнди
источник
источник
Ответы:
Использование параметров помогает предотвратить атаки SQL-инъекций, когда база данных используется вместе с программным интерфейсом, например, настольной программой или веб-сайтом.
В вашем примере пользователь может напрямую запускать код SQL в вашей базе данных, создавая операторы в
txtSalary
.Например, если бы они писали
0 OR 1=1
, выполняемый SQL был быв результате чего все empSalaries будут возвращены.
Кроме того, пользователь может выполнить гораздо худшие команды для вашей базы данных, включая ее удаление, если он написал
0; Drop Table employee
:После этого таблица
employee
будет удалена.В вашем случае похоже, что вы используете .NET. Использовать параметры так же просто, как:
C #
VB.NET
Изменить 2016-4-25:
Согласно комментарию Джорджа Стокера, я изменил пример кода, чтобы не использовать
AddWithValue
. Кроме того, обычно рекомендуется заключатьIDisposable
s вusing
операторы.источник
Insert Into table (Col1, Col2) Values (@Col1, @Col2)
. В свой код вы должны добавить несколькоAddWithValue
s.parameter.Value = someValue
.Вы правы, это связано с SQL-инъекцией , которая представляет собой уязвимость, которая позволяет пользователю malicioius выполнять произвольные операторы для вашей базы данных. Этот старый любимый комикс XKCD иллюстрирует концепцию:
В вашем примере, если вы просто используете:
Вы открыты для SQL-инъекций. Например, скажем, кто-то вводит txtSalary:
Когда вы выполняете этот запрос, он выполнит a
SELECT
и anUPDATE
илиDROP
, или что угодно, что они хотели. В--
конце просто комментируется остальная часть вашего запроса, что было бы полезно при атаке, если бы вы что-либо объединяли послеtxtSalary.Text
.Правильный способ - использовать параметризованные запросы, например (C #):
При этом вы можете безопасно выполнить запрос.
Информацию о том, как избежать SQL-инъекции на нескольких других языках, можно найти на сайте bobby-tables.com , поддерживаемом пользователем SO .
источник
В дополнение к другим ответам необходимо добавить, что параметры не только помогают предотвратить внедрение sql, но и могут повысить производительность запросов . Sql-сервер кэширует параметризованные планы запросов и повторно использует их при выполнении повторяющихся запросов. Если вы не параметризовали свой запрос, тогда sql-сервер будет компилировать новый план для каждого запроса (с некоторым исключением) выполнения, если текст запроса будет отличаться.
Дополнительные сведения о кэшировании плана запроса
источник
Через два года после первой попытки я рецидивирую ...
Почему мы предпочитаем параметры? SQL-инъекция, очевидно, является серьезной причиной, но может быть, мы втайне хотим вернуться к SQL как языку . SQL в строковых литералах - это уже странная культурная практика, но, по крайней мере, вы можете скопировать и вставить свой запрос в среду управления. Динамически построенный SQL с условными операторами и управляющими структурами основного языка, когда в SQL есть условные операторы и управляющие структуры, является варварством нулевого уровня. Вам нужно запустить приложение в режиме отладки или с трассировкой, чтобы увидеть, какой SQL он генерирует.
Не останавливайтесь только на параметрах. Пойдите до конца и используйте QueryFirst (отказ от ответственности: я написал). Ваш SQL находится в файле .sql. Вы редактируете его в великолепном окне редактора TSQL с проверкой синтаксиса и Intellisense для ваших таблиц и столбцов. Вы можете назначить тестовые данные в специальном разделе комментариев и нажать «играть», чтобы запустить запрос прямо в окне. Создать параметр так же просто, как ввести "@myParam" в ваш SQL. Затем при каждом сохранении QueryFirst генерирует оболочку C # для вашего запроса. Ваши параметры появляются, строго типизированные, в качестве аргументов методов Execute (). Ваши результаты возвращаются в IEnumerable или списке строго типизированных POCO, типов, созданных на основе фактической схемы, возвращаемой вашим запросом. Если ваш запрос не выполняется, ваше приложение не скомпилируется. Если ваша схема БД изменяется и ваш запрос выполняется, но некоторые столбцы исчезают, ошибка компиляции указывает на строку в вашем кодекоторый пытается получить доступ к отсутствующим данным. И есть множество других преимуществ. Зачем вам нужен другой способ доступа к данным?
источник
В Sql, когда любое слово содержит знак @, это означает, что оно является переменной, и мы используем эту переменную, чтобы установить в нем значение и использовать его в числовой области в том же sql-скрипте, потому что он ограничен только одним скриптом, в то время как вы можете объявить множество переменных одного типа и имени на многих скриптах. Мы используем эту переменную в партии хранимых процедур, потому что хранимые процедуры представляют собой предварительно скомпилированные запросы, и мы можем передавать значения в эту переменную из сценария, рабочего стола и веб-сайтов для получения дополнительной информации, прочтите Объявление локальной переменной , Хранимую процедуру Sql и инъекции sql .
Также прочтите « Защита от внедрения sql», в котором рассказывается, как защитить свою базу данных.
Надеюсь, это поможет вам понять также любой вопрос, прокомментируйте меня.
источник
Другие ответы объясняют, почему параметры важны, но есть и обратная сторона! В .net есть несколько методов для создания параметров (Add, AddWithValue), но все они требуют, чтобы вы без нужды беспокоились об имени параметра, и все они снижают удобочитаемость SQL в коде. Когда вы пытаетесь медитировать на SQL, вам нужно поискать сверху или снизу, чтобы увидеть, какое значение было использовано в параметре.
Я смиренно заявляю, что мой маленький класс SqlBuilder - самый элегантный способ писать параметризованные запросы . Ваш код будет выглядеть так ...
C #
Ваш код будет короче и удобнее для чтения. Вам даже не нужны дополнительные строки, и, когда вы читаете назад, вам не нужно искать значения параметров. Нужный вам класс здесь ...
источник
AddWithValue
может вызвать проблемы с неявным преобразованием.Старый пост, но хотел убедиться, что новички знают о хранимых процедурах .
Мои 10 центов здесь заключаются в том, что если вы можете написать свой оператор SQL как хранимую процедуру , это, на мой взгляд, является оптимальным подходом. Я ВСЕГДА использую хранимые процедуры и никогда не перебираю записи в основном коде. Для примера:
SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class
.При использовании хранимых процедур вы можете ограничить пользователя только разрешением EXECUTE , что снижает риски безопасности .
Ваша хранимая процедура изначально параметризована, и вы можете указать параметры ввода и вывода.
SELECT
Доступ к хранимой процедуре (если она возвращает данные с помощью оператора) можно получить и прочитать точно так же, как и в случае с обычнымSELECT
оператором в коде.Он также работает быстрее, поскольку компилируется на SQL Server.
Я также упоминал, что вы можете выполнить несколько шагов, например,
update
создать таблицу, проверить значения на другом сервере БД, а затем, когда, наконец, закончить, вернуть данные клиенту, все на том же сервере, и никакого взаимодействия с клиентом. Так что это НАМНОГО быстрее, чем кодирование этой логики в вашем коде.источник