sql - tabla - parametros en report builder
¿Por qué siempre preferimos usar parámetros en las declaraciones SQL? (7)
Soy muy nuevo para trabajar con bases de datos. Ahora puedo escribir comandos SELECT
, UPDATE
, DELETE
e INSERT
. Pero he visto muchos foros donde preferimos escribir:
SELECT empSalary from employee where salary = @salary
...en lugar de:
SELECT empSalary from employee where salary = txtSalary.Text
¿Por qué preferimos siempre usar parámetros y cómo los usaría?
Quería saber el uso y los beneficios del primer método. Incluso he oído hablar de la inyección SQL, pero no la entiendo del todo. Ni siquiera sé si la inyección SQL está relacionada con mi pregunta.
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 almacenamiento en caché del servidor Sql planifica los planes de consultas y los vuelve a utilizar 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 consulta (con alguna exclusión) si el texto de la consulta difiriera.
Más información sobre el almacenamiento en caché del plan de consulta
Dos años después de mi primer intento , estoy reincidiendo ...
¿Por qué preferimos los parámetros? La inyección SQL es obviamente una gran razón, pero podría ser que secretamente anhelamos volver a SQL como un lenguaje . SQL en literales de cadena ya es una práctica cultural extraña, pero al menos puede copiar y pegar su solicitud en el estudio de administración. SQL construido dinámicamente con estructuras de control y condicionales de lenguaje de host, cuando SQL tiene estructuras de control y condicionales, es solo barbarismo de nivel 0. Tienes que ejecutar tu aplicación en depuración, o con un seguimiento, para ver qué SQL genera.
No te detengas solo con los parámetros. Ve todo el camino y usa QueryFirst (descargo de responsabilidad: que escribí). Su SQL vive en un archivo .sql . Usted 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 tu SQL. Luego, cada vez que guarde, QueryFirst genera el contenedor 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 en una 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 compilará. Si su esquema db cambia y su consulta se ejecuta pero algunas columnas desaparecen, el error de compilación apunta a la línea en su código que intenta acceder a los datos faltantes. Y hay muchas otras ventajas. ¿Por qué querrías acceder a los datos de otra forma?
El uso de parámetros ayuda a prevenir los ataques de inyección 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 código SQL directamente en su base de datos creando declaraciones en txtSalary
.
Por ejemplo, si escribieran 0 OR 1=1
, el SQL ejecutado sería
SELECT empSalary from employee where salary = 0 or 1=1
por lo que todos los salarios serían devueltos.
Además, un usuario podría realizar comandos mucho peores en contra de su base de datos, incluida su eliminación si escribieron 0; Drop Table employee
0; Drop Table employee
:
SELECT empSalary from employee where salary = 0; Drop Table employee
El employee
mesa sería eliminado.
En tu caso, parece que estás usando .NET. Usar parámetros es tan fácil como:
DO#
string sql = "SELECT empSalary from employee where salary = @salary";
using (SqlConnection connection = new SqlConnection(/* connection info */))
using (SqlCommand command = new SqlCommand(sql, connection))
{
var salaryParam = new SqlParameter("salary", SqlDbType.Money);
salaryParam.Value = txtMoney.Text;
command.Parameters.Add(salaryParam);
var results = command.ExecuteReader();
}
VB.NET
Dim sql As String = "SELECT empSalary from employee where salary = @salary"
Using connection As New SqlConnection("connectionString")
Using command As New SqlCommand(sql, connection)
Dim salaryParam = New SqlParameter("salary", SqlDbType.Money)
salaryParam.Value = txtMoney.Text
command.Parameters.Add(salaryParam)
Dim results = command.ExecuteReader()
End Using
End Using
Editar 2016-4-25:
Según el comentario de George Stocker, cambié el código de muestra para no usar AddWithValue
. Además, generalmente se recomienda que envuelva IDisposable
s en el using
declaraciones.
En Sql, cuando una palabra contiene @ sign significa que es variable y usamos esta variable para establecer el valor en ella y usarla en el área numérica en la misma secuencia de comandos sql porque solo está restringida en la secuencia de comandos simple mientras que puede declarar muchas variables del mismo tipo y nombre en muchos guiones. Usamos esta variable en el lote de procedimiento almacenado porque el procedimiento almacenado 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 , Sql Stored Procedure e inyecciones sql .
Lea también Protect from sql injection, que le indicará cómo puede proteger su base de datos.
Espero que te ayude a entender también cualquier pregunta comentarme.
Otras respuestas explican por qué los parámetros son importantes, ¡pero hay una desventaja! En .net, hay 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 tratas de meditar en el SQL, debes buscar por encima o por debajo para ver qué valor se ha usado en el parámetro.
Humildemente afirmo que mi pequeña clase SqlBuilder es la manera más elegante de escribir consultas parametrizadas . Tu código se verá así ...
DO#
var bldr = new SqlBuilder( myCommand );
bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId);
//or
bldr.Append("SELECT * FROM CUSTOMERS WHERE NAME LIKE ").FuzzyValue(myName);
myCommand.CommandText = bldr.ToString();
Su código será más corto y mucho más legible. Ni siquiera necesita líneas adicionales y, cuando está leyendo de nuevo, no necesita buscar el valor de los parámetros. La clase que necesitas está aquí ...
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
public class SqlBuilder
{
private StringBuilder _rq;
private SqlCommand _cmd;
private int _seq;
public SqlBuilder(SqlCommand cmd)
{
_rq = new StringBuilder();
_cmd = cmd;
_seq = 0;
}
public SqlBuilder Append(String str)
{
_rq.Append(str);
return this;
}
public SqlBuilder Value(Object value)
{
string paramName = "@SqlBuilderParam" + _seq++;
_rq.Append(paramName);
_cmd.Parameters.AddWithValue(paramName, value);
return this;
}
public SqlBuilder FuzzyValue(Object value)
{
string paramName = "@SqlBuilderParam" + _seq++;
_rq.Append("''%'' + " + paramName + " + ''%''");
_cmd.Parameters.AddWithValue(paramName, value);
return this;
}
public override string ToString()
{
return _rq.ToString();
}
}
Publicación anterior pero quería asegurarse de que los recién llegados conozcan los procedimientos almacenados.
Mi valor de 10 centavos aquí es que si puede escribir su declaración de SQL como un procedimiento almacenado, eso en mi opinión es el enfoque óptimo. SIEMPRE uso procs almacenados y nunca recorro los registros en mi código principal. Por ejemplo: Tabla SQL> Procedimientos almacenados de SQL> IIS / Dot.NET> Clase.
Cuando utiliza procedimientos almacenados, puede restringir al usuario para que ejecute el permiso EXECUTE, lo que reduce los riesgos de seguridad.
Su procedimiento almacenado está intrínsecamente parametrizado, y puede especificar parámetros de entrada y salida.
El procedimiento almacenado (si devuelve datos a través de la instrucción SELECT) se puede acceder y leer de la misma manera que lo haría con una instrucción SELECT normal en su código.
También se ejecuta más rápido, ya que se compila en el servidor SQL.
¿También mencioné que puede hacer varios pasos, por ejemplo, actualizar una tabla, verificar valores en otro servidor de bases de datos y finalmente, una vez finalizado, devolver datos al cliente, todo en el mismo servidor y sin interacción con el cliente. Así que esto es MUCHO más rápido que codificar esta lógica en tu código.
Tiene razón, esto está relacionado con la inyección SQL , que es una vulnerabilidad que permite a un usuario de malicious ejecutar sentencias arbitrarias en su base de datos. Este viejo cómic XKCD favorito ilustra el concepto:
En tu ejemplo, si solo usas:
var query = "SELECT empSalary from employee where salary = " + txtSalary.Text;
// and proceed to execute this query
Estás abierto a la inyección SQL. Por ejemplo, digamos que alguien ingresa txtSalary:
1; UPDATE employee SET salary = 9999999 WHERE empID = 10; --
1; DROP TABLE employee; --
// etc.
Cuando ejecuta esta consulta, realizará un SELECT
y una UPDATE
o DROP
, o lo que quisieran. El --
al final simplemente comenta el resto de tu consulta, lo que sería útil en el ataque si estuvieras concatenando algo después de txtSalary.Text
.
La forma correcta es usar consultas parametrizadas, por ejemplo, (C #):
SqlCommand query = new SqlCommand("SELECT empSalary FROM employee
WHERE salary = @sal;");
query.Parameters.AddWithValue("@sal", txtSalary.Text);
Con eso, puede ejecutar la consulta de forma segura.
Para 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 .