Soy muy nuevo en el trabajo con bases de datos. Ahora puedo escribir SELECT
, UPDATE
, DELETE
, y INSERT
comandos. Pero he visto muchos foros donde preferimos escribir:
SELECT empSalary from employee where salary = @salary
...en vez de:
SELECT empSalary from employee where salary = txtSalary.Text
¿Por qué siempre preferimos usar parámetros y cómo los usaría?
Quería conocer el uso y los beneficios del primer método. Incluso he oído hablar de la inyección SQL pero no lo entiendo del todo. Ni siquiera sé si la inyección SQL está relacionada con mi pregunta.
sql
sql-server
sql-injection
Arenoso
fuente
fuente
Respuestas:
El uso de parámetros ayuda a prevenir ataques de inyección de SQL cuando la base de datos se utiliza junto con una interfaz de programa, como un programa de escritorio o un sitio web.
En su ejemplo, un usuario puede ejecutar directamente código SQL en su base de datos creando declaraciones en formato
txtSalary
.Por ejemplo, si tuvieran que escribir
0 OR 1=1
, el SQL ejecutado seríapor lo que todos los empSalaries serían devueltos.
Además, un usuario podría ejecutar comandos mucho peores en su base de datos, incluida su eliminación si escribiera
0; Drop Table employee
:employee
Luego, la tabla se eliminaría.En su caso, parece que está utilizando .NET. Usar parámetros es tan fácil como:
C#
VB.NET
Editar 2016-4-25:
Según el comentario de George Stocker, cambié el código de muestra para que no lo use
AddWithValue
. Además, generalmente se recomienda que incluyaIDisposable
s enusing
declaraciones.fuente
Insert Into table (Col1, Col2) Values (@Col1, @Col2)
. En su código, agregaría variosAddWithValue
s.parameter.Value = someValue
.Tiene razón, esto está relacionado con la inyección SQL , que es una vulnerabilidad que permite a un usuario malicioso ejecutar declaraciones arbitrarias en su base de datos. Este cómic XKCD favorito de antaño ilustra el concepto:
En su ejemplo, si solo usa:
Estás abierto a la inyección SQL. Por ejemplo, digamos que alguien ingresa txtSalary:
Cuando ejecute esta consulta, realizará un
SELECT
y unUPDATE
oDROP
, o lo que quieran. El--
al final simplemente comenta el resto de su consulta, lo que sería útil en el ataque si estuviera concatenando algo despuéstxtSalary.Text
.La forma correcta es utilizar consultas parametrizadas, por ejemplo (C #):
Con eso, puede ejecutar la consulta de forma segura.
Para obtener referencia sobre cómo evitar la inyección de SQL en varios otros idiomas, consulte bobby-tables.com , un sitio web mantenido por un usuario de SO .
fuente
Además de otras respuestas, es necesario agregar que los parámetros no solo ayudan a prevenir la inyección de SQL, sino que también pueden mejorar el rendimiento de las consultas . El servidor SQL almacena en caché los planes de consulta parametrizados y los reutiliza en la ejecución de consultas repetidas. Si no parametrizó su consulta, el servidor sql compilaría un nuevo plan en cada ejecución de la consulta (con alguna exclusión) si el texto de la consulta fuera diferente.
Más información sobre el almacenamiento en caché del plan de consultas
fuente
Dos años después de mi primer intento , estoy reincidiendo ...
¿Por qué preferimos los parámetros? La inyección de SQL es obviamente una gran razón, pero podría ser que en secreto anhelemos volver a SQL como lenguaje . SQL en cadenas literales ya es una práctica cultural extraña, pero al menos puede copiar y pegar su solicitud en Management Studio. SQL construido dinámicamente con condicionales del lenguaje host y estructuras de control, cuando SQL tiene condicionales y estructuras de control, es simplemente una barbarie de nivel 0. Tienes que ejecutar tu aplicación en depuración, o con un seguimiento, para ver qué SQL genera.
No se detenga solo con los parámetros. Vaya hasta el final y use QueryFirst (descargo de responsabilidad: que escribí). Tu SQL vive en un archivo .sql. Lo edita en la fabulosa ventana del editor TSQL, con validación de sintaxis e Intellisense para sus tablas y columnas. Puede asignar datos de prueba en la sección de comentarios especiales y hacer clic en "reproducir" para ejecutar su consulta allí mismo en la ventana. Crear un parámetro es tan fácil como poner "@myParam" en su SQL. Luego, cada vez que guarde, QueryFirst genera el contenedor de C # para su consulta. Sus parámetros aparecen, fuertemente tipados, como argumentos para los métodos Execute (). Sus resultados se devuelven en un IEnumerable o Lista de POCO fuertemente tipados, los tipos generados a partir del esquema real devuelto por su consulta. Si su consulta no se ejecuta, su aplicación no se compilará. Si su esquema de base de datos cambia y su consulta se ejecuta pero algunas columnas desaparecen, el error de compilación apunta a la línea en su códigoque intenta acceder a los datos faltantes. Y hay muchas otras ventajas. ¿Por qué querría acceder a los datos de otra manera?
fuente
En Sql, cuando cualquier palabra contiene el signo @, significa que es variable y usamos esta variable para establecer un valor en ella y usarla en el área numérica en el mismo script sql porque solo está restringido en un único script, mientras que puede declarar muchas variables del mismo tipo y nombre en muchos guiones. Usamos esta variable en el lote de procedimientos almacenados porque los procedimientos almacenados son consultas precompiladas y podemos pasar valores en estas variables desde el script, el escritorio y los sitios web para obtener más información, lea Declarar variable local , Procedimiento almacenado SQL e inyecciones SQL .
También lea Protect from sql injection , le guiará sobre cómo puede proteger su base de datos.
Espero que te ayude a entender también cualquier pregunta comentenme.
fuente
Otras respuestas cubren por qué los parámetros son importantes, ¡pero hay una desventaja! En .net, existen varios métodos para crear parámetros (Add, AddWithValue), pero todos requieren que se preocupe, innecesariamente, por el nombre del parámetro, y todos reducen la legibilidad del SQL en el código. Justo cuando intentas meditar en SQL, necesitas buscar por encima o por debajo para ver qué valor se ha utilizado en el parámetro.
Humildemente afirmo que mi pequeña clase SqlBuilder es la forma más elegante de escribir consultas parametrizadas . Tu código se verá así ...
C#
Su código será más corto y mucho más legible. Ni siquiera necesita líneas adicionales y, cuando está leyendo, no necesita buscar el valor de los parámetros. La clase que necesitas está aquí ...
fuente
AddWithValue
puede causar problemas de conversión implícita.Publicación anterior, pero quería asegurarse de que los recién llegados conozcan los procedimientos almacenados .
Mi valor de 10 ¢ aquí es que si puede escribir su declaración SQL como un procedimiento almacenado , en mi opinión, ese es el enfoque óptimo. Yo SIEMPRE utilizar procedimientos almacenados y nunca se bucle a través de los registros en mi código principal. Por ejemplo:
SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class
.Cuando utiliza procedimientos almacenados, puede restringir al usuario a EJECUTAR solo el permiso, lo que reduce los riesgos de seguridad. .
Su procedimiento almacenado está intrínsecamente paramerizado y puede especificar parámetros de entrada y salida.
Se
SELECT
puede acceder al procedimiento almacenado (si devuelve datos a través de una declaración) y leerlo exactamente de la misma manera que lo haría con unSELECT
declaración en su código.También se ejecuta más rápido ya que se compila en SQL Server.
¿También mencioné que puede hacer varios pasos, por ejemplo,
update
una tabla, verificar valores en otro servidor de base de datos y luego, una vez que finalmente haya terminado, devolver los datos al cliente, todo en el mismo servidor y sin interacción con el cliente? Entonces esto es MUCHO más rápido que codificar esta lógica en su código.fuente