Eu sou muito novo no trabalho com bancos de dados. Agora eu posso escrever SELECT
, UPDATE
, DELETE
, e INSERT
comandos. Mas eu vi muitos fóruns onde preferimos escrever:
SELECT empSalary from employee where salary = @salary
...ao invés de:
SELECT empSalary from employee where salary = txtSalary.Text
Por que sempre preferimos usar parâmetros e como eu os usaria?
Eu queria saber o uso e os benefícios do primeiro método. Já ouvi falar de injeção de SQL, mas não entendo muito bem. Eu nem sei se injeção de SQL está relacionada à minha dúvida.
sql
sql-server
sql-injection
Sandy
fonte
fonte
Respostas:
O uso de parâmetros ajuda a evitar ataques de injeção de SQL quando o banco de dados é usado em conjunto com uma interface de programa, como um programa de desktop ou site.
Em seu exemplo, um usuário pode executar diretamente o código SQL em seu banco de dados elaborando instruções em
txtSalary
.Por exemplo, se eles fossem escrever
0 OR 1=1
, o SQL executado seriaem que todos os empSalaries seriam devolvidos.
Além disso, um usuário poderia executar comandos muito piores em seu banco de dados, incluindo excluí-lo se escrevesse
0; Drop Table employee
:A tabela
employee
seria então excluída.No seu caso, parece que você está usando .NET. Usar parâmetros é tão fácil quanto:
C #
VB.NET
Editar 2016-4-25:
De acordo com o comentário de George Stocker, alterei o código de amostra para não usar
AddWithValue
. Além disso, geralmente é recomendado que você envolvaIDisposable
s emusing
instruções.fonte
Insert Into table (Col1, Col2) Values (@Col1, @Col2)
. Em seu código, você adicionaria váriosAddWithValue
s.parameter.Value = someValue
.Você está certo, isso está relacionado à injeção de SQL , que é uma vulnerabilidade que permite que um usuário malicioso execute declarações arbitrárias contra o seu banco de dados. Este quadrinho favorito dos velhos tempos XKCD ilustra o conceito:
No seu exemplo, se você apenas usar:
Você está aberto à injeção de SQL. Por exemplo, digamos que alguém insira txtSalary:
Quando você executar esta consulta, ela executará um
SELECT
e umUPDATE
ouDROP
, ou o que quiserem. O--
no final simplesmente comenta o resto da sua consulta, o que seria útil no ataque se você estivesse concatenando algo depoistxtSalary.Text
.A maneira correta é usar consultas parametrizadas, por exemplo (C #):
Com isso, você pode executar a consulta com segurança.
Para referência sobre como evitar injeção de SQL em vários outros idiomas, verifique bobby-tables.com , um site mantido por um usuário SO .
fonte
Além de outras respostas, é necessário adicionar que os parâmetros não apenas ajudam a prevenir a injeção de sql, mas podem melhorar o desempenho das consultas . Planos de consulta parametrizados de cache do servidor SQL e reutilizá-los na execução de consultas repetidas. Se você não parametrizou sua consulta, o sql server compilará um novo plano em cada execução da consulta (com alguma exclusão) se o texto da consulta for diferente.
Mais informações sobre o cache do plano de consulta
fonte
Dois anos depois da minha primeira tentativa , estou recidivando ...
Por que preferimos parâmetros? A injeção de SQL é obviamente um grande motivo, mas pode ser que estejamos secretamente desejando voltar ao SQL como linguagem . SQL em strings literais já é uma prática cultural estranha, mas pelo menos você pode copiar e colar sua solicitação no estúdio de gerenciamento. O SQL construído dinamicamente com condicionais da linguagem host e estruturas de controle, quando o SQL tem condicionais e estruturas de controle, é apenas barbarismo de nível 0. Você tem que executar seu aplicativo em depuração, ou com um rastreamento, para ver qual SQL ele gera.
Não pare apenas com parâmetros. Vá até o fim e use o QueryFirst (isenção de responsabilidade: que escrevi). Seu SQL reside em um arquivo .sql que tenta acessar os dados ausentes. E existem inúmeras outras vantagens. Por que você deseja acessar os dados de outra forma?. Você o edita na fabulosa janela do editor TSQL, com validação de sintaxe e Intellisense para suas tabelas e colunas. Você pode atribuir dados de teste na seção de comentários especiais e clicar em "reproduzir" para executar sua consulta ali mesmo na janela. Criar um parâmetro é tão fácil quanto colocar "@myParam" em seu SQL. Então, cada vez que você salva, o QueryFirst gera o wrapper C # para sua consulta. Seus parâmetros aparecem, fortemente tipados, como argumentos para os métodos Execute (). Seus resultados são retornados em um IEnumerable ou Lista de POCOs fortemente tipados, os tipos gerados a partir do esquema real retornado por sua consulta. Se sua consulta não for executada, seu aplicativo não será compilado. Se seu esquema de banco de dados mudar e sua consulta for executada, mas algumas colunas desaparecerem, o erro de compilação apontará para a linha em seu código
fonte
No Sql, quando qualquer palavra contém o sinal @, significa que é variável e usamos esta variável para definir o valor nela e usá-la na área de número no mesmo script sql porque é restrito apenas no script único enquanto você pode declarar muitas variáveis do mesmo tipo e nome em muitos scripts. Usamos essa variável no lote de procedimento armazenado porque procedimento armazenado são consultas pré-compiladas e podemos passar valores nessas variáveis de script, desktop e sites para obter mais informações, leia Declare Local Variable , Sql Stored Procedure e injeções de sql .
Leia também Proteger contra injeção de sql, que irá guiar como você pode proteger seu banco de dados.
Espero que ajude você a entender também qualquer dúvida me comente.
fonte
Outras respostas cobrem por que os parâmetros são importantes, mas há uma desvantagem! Em .net, existem vários métodos para criar parâmetros (Add, AddWithValue), mas todos eles exigem que você se preocupe, desnecessariamente, com o nome do parâmetro e todos reduzem a legibilidade do SQL no código. Bem quando você está tentando meditar sobre o SQL, você precisa procurar acima ou abaixo para ver qual valor foi usado no parâmetro.
Eu humildemente afirmo que minha pequena classe SqlBuilder é a maneira mais elegante de escrever consultas parametrizadas . Seu código ficará assim ...
C #
Seu código será mais curto e muito mais legível. Você nem mesmo precisa de linhas extras e, quando está lendo de volta, não precisa ficar procurando o valor dos parâmetros. A aula que você precisa está aqui ...
fonte
AddWithValue
pode causar problemas de conversão implícitos.Postagem antiga, mas queria garantir que os novatos estão cientes dos procedimentos armazenados .
Meu valor de 10 centavos aqui é que, se você for capaz de escrever sua instrução SQL como um procedimento armazenado , essa é a abordagem ideal. SEMPRE uso procs armazenados e nunca faço loop pelos registros em meu código principal. Por Exemplo:
SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class
.Ao usar procedimentos armazenados, você pode restringir o usuário apenas à permissão EXECUTAR , reduzindo assim os riscos de segurança .
Seu procedimento armazenado é inerentemente paramerizado e você pode especificar parâmetros de entrada e saída.
O procedimento armazenado (se retornar dados por meio de uma
SELECT
instrução) pode ser acessado e lido exatamente da mesma maneira que você faria com umaSELECT
instrução normal em seu código.Ele também é executado com mais rapidez, pois é compilado no SQL Server.
Eu também mencionei que você pode fazer várias etapas, por exemplo,
update
uma tabela, verificar os valores em outro servidor de banco de dados e, quando finalmente terminar, retornar os dados para o cliente, tudo no mesmo servidor, e sem interação com o cliente. Portanto, isso é MUITO mais rápido do que codificar essa lógica em seu código.fonte