Soy muy nuevo para trabajar con bases de datos. Ahora puedo escribir SELECT, UPDATE, DELETE, y INSERT comandos. Pero he visto en muchos foros en los que preferimos escribir:

SELECT empSalary from employee where salary = @salary

…en vez de:

SELECT empSalary from employee where salary = txtSalary.Text

¿Por qué siempre prefiere el uso de los parámetros y cómo puedo usar?

Quería saber el uso y los beneficios del primer método. Incluso he oído hablar de inyección de SQL, pero yo no la entiendes. Ni siquiera sé si la inyección de SQL es relacionado con mi pregunta.

  • Tienes razón, esto está relacionado con la inyección de SQL. Cómo lidiar con los parámetros por lo general es responsabilidad de cualquier lenguaje/framework se ejecuta el programa, y puede ser el idioma a cargo. Por favor, publique su RDBMS (útil), y ORM marco jurídico (necesario).
  • Estoy utilizando C# como lenguaje de programación y Sql Server 2008 como base de datos. Estoy usando Microsoft dotNet framework 4.0. Estoy realmente lo siento, que no estoy seguro de lo que están pidiendo (RDBMS o ORM), tal vez usted me puede dar mi RDBMS y ORM marco versiones ahora :-). Muchas gracias
  • RDBMS es su base de datos, en el caso de SQL Server 2008. ORM es el método por el cual se está accediendo a la base de datos, en este caso, ADO.NET. Otros includ LINQ to SQL y Entity Framework. De hecho, una vez que aprenda los conceptos básicos de ADO.NET y SQL, recomiendo el uso de un ORM como LINQ o EF, ya que cuidar de muchos de los asuntos que le encuentro manualmente escribiendo SQL.
InformationsquelleAutor Sandy | 2011-09-21

7 Comentarios

  1. 114

    El uso de parámetros ayuda a prevenir ataques de Inyección de SQL cuando la base de datos se utiliza en conjunción con una interfaz de programa como un programa de escritorio o sitio web.

    En el ejemplo, un usuario puede ejecutar directamente el código SQL en su base de datos mediante la elaboración de declaraciones en txtSalary.

    Por ejemplo, si se escribe 0 OR 1=1, el SQL ejecutada sería

     SELECT empSalary from employee where salary = 0 or 1=1

    de la cual todos los empSalaries sería devuelto.

    Además, un usuario podría realizar mucho peor comandos en contra de su base de datos, incluyendo la eliminación de que Si escribieron 0; Drop Table employee:

    SELECT empSalary from employee where salary = 0; Drop Table employee

    La tabla employee entonces sería eliminado.


    En su caso, parece que estás usando .NET. El uso de parámetros es tan fácil como:

    C#

    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:

    Como por George Stocker comentario, he cambiado el código de ejemplo para no utilizar AddWithValue. También, se recomienda que ajuste IDisposables en using declaraciones.

    • de gran ayuda. sólo mediante la lectura de esta solución, lo primero que hice es tratado de hackear mi propio programa. y volla, yo lo hice correctamente. Gracias de nuevo
    • gran solución. Pero, ¿puedes explicar un poco más, ¿por qué y cómo el uso de parámetros es seguro. Me refiero a que aún se ve como el comando sql que va a ser el mismo
    • podemos añadir varios parámetros de comando sql. Como podemos exigir en un Comando INSERT?
    • SQL Server trata el texto dentro de los parámetros de entrada única y nunca va a ejecutar.
    • Sí, usted puede agregar múltiples parámetros: Insert Into table (Col1, Col2) Values (@Col1, @Col2). En el código se había añadir múltiples AddWithValues.
    • ¿Cómo puedo utilizar el código de C# para permitir que varios variable?
    • Por favor, no use AddWithValue! Puede causar la conversión implícita de problemas. Siempre ajuste el tamaño de forma explícita y agregar el valor del parámetro con parameter.Value = someValue.
    • Haciendo la forma de hacer alaways me lanza un OdbcException la tecla @escalar de variable debe ser declarada. No entiendo por qué. He doublechecked que la clave es la misma y en la consulta de su escrito con una ‘@’. Puede ser porque es un DateType o porque estoy usando un OdbcConnection en lugar de sql?
    • Tengo.. ODBC, no sólo de apoyo «?» como parámetro. La inserción de Parámetro se distingue por los parámetros de orden. ver aquí
    • Realmente debería usar salaryParam.Value = CDec(txtMoney.Text): SQL Server money es Decimal en .NET: Tipo de Datos SQL Server Asignaciones. Y el nombre del parámetro de las necesidades de la «@», como en «@salario».
    • Hay un reemplazo para SqlParameter.Add() que te permite hacer todos los parámetros anteriores-la adición de una línea. Las tres líneas que se convertiría command.Parameters.Add("salary", SqlDbType.Money).Value = txtMoney.Text;

  2. 68

    Tienes razón, esto está relacionado con La inyección de SQL, que es una vulnerabilidad que permite a un malicioius usuario para ejecutar arbitraria declaraciones en contra de su base de datos. Este tiempo viejo favorito Comic de XKCD ilustra el concepto:

    ¿Por qué siempre prefiere el uso de parámetros en las instrucciones SQL?


    En tu ejemplo, si usted sólo tiene que utilizar:

    var query = "SELECT empSalary from employee where salary = " + txtSalary.Text;
    // and proceed to execute this query

    Usted está abierto a la inyección de SQL. Por ejemplo, digamos que alguien entra txtSalary:

    1; UPDATE employee SET salary = 9999999 WHERE empID = 10; --
    1; DROP TABLE employee; --
    // etc.

    Al ejecutar esta consulta, se llevará a cabo un SELECT y un UPDATE o DROP, o lo que querían. El -- al final simplemente comentarios que el resto de tu consulta, lo cual sería muy útil en el ataque si se fueron concatenando nada después de txtSalary.Text.


    La forma correcta es utilizar consultas con parámetros, por ejemplo, (C#):

    SqlCommand query =  new SqlCommand("SELECT empSalary FROM employee 
                                        WHERE salary = @sal;");
    query.Parameters.AddWithValue("@sal", txtSalary.Text);

    Con eso, usted puede ejecutar la consulta.

    De referencia sobre cómo evitar la inyección de código SQL en varios idiomas, check bobby-tables.com, un sitio web mantenido por un De MANERA que el usuario.

    • inyecciones SQL en placas de vehículo
    • gran solución. Pero, ¿puedes explicar un poco más, ¿por qué y cómo el uso de parámetros es seguro. Me refiero a que aún se ve como el comando sql que va a ser el mismo.
    • un concepto erróneo común – que todavía creen que la consulta con parámetros que tendrá en el valor y la sustituir los parámetros para los valores reales – a la derecha? No esto no está sucediendo! – al contrario, la instrucción SQL con parámetros serán transmitidos a SQL Server, junto con una lista de parámetros y sus valores – la instrucción SQL es no va a ser el mismo
    • eso significa que la inyección de sql está siendo monitoreado por sql server mecanismo interno o la seguridad. gracias.
    • Tanto como me gusta los dibujos animados, si usted está ejecutando su código con privilegios suficientes para colocar tablas, probablemente más amplia de cuestiones.
    • gran dibujo animado 😀
    • La mejor respuesta que he visto en

  3. 5

    Además de las otras respuestas es menester añadir que los parámetros no sólo ayuda a prevenir la inyección de sql, pero puede mejorar el rendimiento de las consultas. Sql servidor de almacenamiento en caché de consultas con parámetros planes y reutilización de ellos en repetidas consultas de ejecución. Si usted no tiene parámetros de su consulta, a continuación, sql server podría compilar nuevo plan en cada consulta(con exclusión) de ejecución si el texto de la consulta sería diferente.

    Más información acerca de la consulta del plan de almacenamiento en caché

    • Esto es más pertinente de lo que uno podría pensar. Incluso un «pequeño» de la consulta puede ser ejecutado a miles o millones de veces, efectivamente el lavado de la totalidad de la caché de consultas.
  4. 3

    En Sql cuando cualquier palabra contienen @ signo significa que es variable y utilizar esta variable para establecer el valor en él y usarlo en el número de la zona en la misma secuencia de comandos sql, ya que sólo está restringido en la única secuencia de comandos mientras se pueden declarar varias variables del mismo tipo y el nombre de muchos de secuencia de comandos. Utilizamos esta variable en el procedimiento almacenado mucho porque procedimiento almacenado son pre-compilado consultas y podemos pasar valores de estas variables de secuencia de comandos, de escritorio y sitios web para obtener más información, lea la Declarar Una Variable Local, Procedimiento Almacenado De Sql y las inyecciones de sql.

    Lea también Proteger de la inyección de sql será una guía de cómo usted puede proteger su base de datos.

    La esperanza de que ayudará a entender también cualquier pregunta, comentario mí.

  5. 3

    Dos años después de mi primer vaya, estoy recidivating…

    ¿Por qué preferimos los parámetros? La inyección SQL es, obviamente, una gran razón, pero podría ser que estamos secreto anhelo de volver a SQL como un lenguaje. SQL en los literales de cadena ya es un extraño a la práctica cultural, pero al menos se puede copiar y pegar su solicitud en management studio. SQL dinámicamente construido con el idioma de acogida, las condicionales y las estructuras de control, cuando SQL tiene las condicionales y las estructuras de control, es sólo en el nivel 0 de la barbarie. Usted tiene que ejecutar la aplicación en la depuración, o con un seguimiento, para ver lo que SQL que genera.

    No solamente a los parámetros. Ir todo el camino y el uso QueryFirst (descargo de responsabilidad: la que escribí). SQL vidas en una .archivo sql. Modifica en el fabuloso TSQL ventana de editor, con validación de sintaxis y de Intellisense para las tablas y columnas. Puede asignar los datos de prueba en el especial de la sección de comentarios y haga clic en «jugar» para ejecutar su derecho de consulta que hay en la ventana. Creación de un parámetro es tan fácil como poner «@myParam» en el SQL. Entonces, cada vez que se guarda, QueryFirst genera el C# contenedor para su consulta. Sus parámetros de pop-up, inflexible, como argumentos para la Ejecución() métodos. Los resultados se devuelven en un IEnumerable o Lista de inflexible POCOs, los tipos generados desde el esquema real devueltos por la consulta. Si la consulta no se ejecuta, su aplicación no va a compilar. Si tu db cambios de esquema y su consulta se ejecuta pero algunas columnas desaparecen, el error de compilación puntos a la línea en el código que intenta acceder a los datos que faltan. Y hay otras numerosas ventajas. ¿Por qué quieres acceder a los datos de otra manera?

  6. 2

    Otras respuestas cubierta por qué parámetros son importantes, pero hay un inconveniente! En .net, existen varios métodos para la creación de parámetros (Agregar, AddWithValue), pero todos ellos requieren que usted se preocupe, innecesariamente, sobre el nombre del parámetro, y que todo se reduzca la legibilidad del SQL en el código. A la derecha cuando usted está tratando de meditar en el SQL, usted necesita a cazar alrededor de arriba o de abajo para ver qué valor ha sido utilizado en el parámetro.

    Humildemente me reclamo mi pequeño SqlBuilder clase es la forma más elegante para escribir consultas parametrizadas. El código se verá así…

    C#

    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. Usted incluso no necesita más líneas, y, cuando estás leyendo, no necesitas buscar alrededor para el valor de los parámetros. La clase que usted necesita 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();
    }
    }
    • Nomenclatura de sus parámetros de ayuda, sin duda, cuando el perfil de la consulta el servidor se está ejecutando.
    • Mi jefe me dijo la misma cosa. Si los significativos nombres de los parámetros son importantes para usted, añadir un paramName argumento para el método de valor. Sospecho que estás complicar las cosas innecesariamente.
    • Mala idea. Como se dijo antes, AddWithValue puede causar la conversión implícita de problemas.
    • tienes razón, pero eso no impide que AddWithValue() se utilizan muy ampliamente, y creo que no invalida la idea. Pero mientras tanto, me he encontrado con un mejores de la escritura de consultas con parámetros, y que no utilice AddWithValue() 🙂
    • A la derecha! Prometo que me voy a mirar que pronto!
  7. 0

    Viejo post, pero quería asegurarse de los recién llegados son conscientes de procedimientos Almacenados.

    Mis 10¢ vale la pena aquí es que si usted es capaz de escribir su instrucción SQL como una procedimiento almacenado, que en mi opinión es el enfoque óptimo. Yo SIEMPRE el uso de procedimientos almacenados y nunca bucle a través de los registros en mi código principal. Por Ejemplo: SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class.

    Cuando se utilizan procedimientos almacenados, puede restringir al usuario EJECUTAR permiso, por lo que la reducción de los riesgos de seguridad.

    El procedimiento almacenado es inherentemente paramerised, y usted puede especificar los parámetros de entrada y salida.

    El procedimiento almacenado (si devuelve los datos a través de SELECT declaración) se puede acceder y leer exactamente de la misma manera como se haría con cualquier SELECT declaración en el código.

    También se ejecuta más rápido como es compilado en el Servidor SQL server.

    Hizo también he de mencionar que usted puede hacer varios pasos, por ejemplo, update una tabla, compruebe los valores en otro servidor de DB, y luego, una vez terminado, los datos de retorno para el cliente, todo en el mismo servidor, y no hay interacción con el cliente. Así que esto es MUCHO más rápido que la codificación de esta lógica en el código.

Dejar respuesta

Please enter your comment!
Please enter your name here