lenguaje SQL, Bases de datos, Procedimientos Almacenados y SQL server

Lenguaje SQL - Bases de datos - SQL Server

    
  Buscar   

Inicio

Help Desk

Foros SQL

Tutoriales SQL
 General
 Lenguaje SQL
 SQL Server
 MySQL
 Proc. Almacenados
 Programación .NET

Manuales SQL

Libros SQL

Enlaces

Programacion

Acerca de...

Entrar
Registro

Lenguaje SQL, bases de datos y SQL Server

MSDN: U.S. Local Highlights
The latest developer information for the United States.
  • Read the Amazing Adventures of Kevlarr and the Security Development Lifecycle
    Follow the quest of Kevlarr, an ordinary software developer, as he learns to find his inner super powers to build and protect a more fortified application. Will he succeed in time for launch?

  • See What's Happening in the Windows Internet Explorer Developer Center
    Visit the Windows Internet Explorer Developer Center to try out Internet Explorer 8 Beta 2 and get access to resources for building great-looking, cross-browser Web sites.

  • Introducing Expression Blend to Silverlight 2 Developers
    Watch this video to find out more about Expression Blend.


    Last Refreshed 1/6/2009 12:33:31 AM

  •  


    Inicio > Tutoriales SQL > Procedimientos Almacenados    
    SQL Dinámico: Exec y sp_executeSql

    Enviado por   el Sunday, February 15, 2004 (Her)

    La ejecución dinámica de instrucciones SQL es una potente herramienta a la que tarde o temprano tenemos que enfrentarnos.

    SQL Dinámico: Exec y sp_executeSql

    La ejecución dinámica de instrucciones SQL es algo a lo que tarde o temprano (más bien temprano) tenemos que enfrentarnos. Y ya que tenemos que hacerlo más vale saber como funciona y tener un poco de cuidado… (ver artículo de inyección de código)

    Por qué dinámico
    Hablamos de ejecución dinámica porque la sentencia SQL que va a ejecutar nuestro servidor no esta escrita en ningún sitio, sino que se crea cada vez que tenemos que ejecutarla. Frente a esta forma de trabajar tenemos el SQL “normal”, donde la sentencia SQL esta previamente escrita y lo único que hay que hacer es decidir cuando la ejecutamos.

    Tipos de SQL dinámico
    Siempre es difícil hacer una clasificación, pero en este caso vamos a intentar diferenciar el SQL dinámico que se crea en el servidor y el que creamos en nuestras aplicaciones.
    Por ejemplo si trabajamos en Visual Basic NET y en nuestro código tenemos algo como esto:

    Dim sSQL as string
    Dim entrada as string
    Dim miCon As New SqlConnection(“cadena conexión”)
    ‘de alguna manera el usuario escribe una condición
    ‘y metemos ese valor en la variable entrada
    sSQL=”SELECT * FROM Clientes WHERE Nombre =“
    sSQL=sSQL + “’” + entrada + “`”
    Dim cmdProductos As New SqlCommand(sSQL, miCon)
    cmdProductos.CommandType = CommandType.Text
    miCon.Open()
    . . . =cmdProductos.ExecuteReader()
    ‘ y todo lo que haga falta para usar los datos devueltos . . .

    Esto sería SQL dinámico generado en el cliente.
    Pero no es esto lo que nos interesa. Nosotros vamos a centrarnos en el SQL generado en el servidor, generalmente dentro de un procedimiento almacenado.
    Primero veamos como podemos pasar el código anterior a un procedimiento almacenado que recibe un parámetro:

    CREATE PROCEDURE VerProductos @Nombre varchar(50) AS
    SELECT * FROM Productos WHERE Nombre = @ArticleID
    GO

    ¿Más o menos lo mismo no? Pues sí, pero no.
    La diferencia está en que cuando creamos la sentencia desde el cliente podemos hacer prácticamente de todo para editar y construir esa sentencia. Y cuando lo hacemos un procedimiento almacenado tenemos limitaciones a la hora de utilizar variables para construir nuestra sentencia.
    Supongamos que necesitamos una sentencia SQL donde la parte dinámica es el nombre de la tabla. Parece lógico escribir algo así:

    CREATE PROCEDURE ElegirTabla @NombreTabla VarChar(128) AS
    SELECT * FROM @NombreTabla
    GO

    Pero si lo ejecutamos lo único que obtenemos es un error.

    Incorrect syntax near '@NombreTalba'

    ¡No podemos utilizar variables en cualquier parte de una sentencia! Por ejemplo no podemos utilizarlas en la cláusula FROM. 

    Ejecutar SQL dinámico con EXEC
    Ahora es cuando ya tenemos que utilizar SQL dinámico de servidor propiamente dicho. Para solucionar el error de antes generaremos dentro de nuestro procedimiento almacenado una sentencia en una variable de texto como hacíamos desde Visual Basic NET y luego le diremos al SQL Server que ejecute esa sentencia mediante el comando EXEC.

    CREATE PROCEDURE ElegirTabla @NombreTabla VarChar(128) AS
    DECLARE @sSQL VarChar(1000)
    --El truco esta en tener la sentencia dentro de una variable
    SELECT sSQL = 'SELECT * FROM '
    SELECT @sSQL = @SQL + @NombreTabla
    --Y ejecutar ese texto contenido en nuestra variable
    EXEC ( @sSQL)
    GO

    Como vemos es sencillo, pero utilizar el SQL así dentro de un procedimiento almacenado nos ocasiona dos problemas.
    En primer lugar utilizar así los parámetros da lugar a problemas de seguridad porque estamos permitiendo que el usuario utilice trucos de inyección de código y que nuestro procedimiento almacenado haga cosas para las que no fue creado.
    Un ejemplo de lo que alguien podría llegar a hacer es:

    EXEC ElegirTabla ' Clientes GO DROP TABLE Pedidos'

    Que un usuario pueda ejecutar sentencias como esta no es algo muy deseable verdad.

    El segundo problema que nos plantea el uso de EXEC es de rendimiento. Como ya sabemos una de las ventajas de los procedimientos almacenados es que cuando se ejecuta la primera vez se compila, y no es necesario recompilarlo en ejecuciones sucesivas. Pero esto deja de ser cierto cuando usamos EXEC para ejecutar SQL dinámico porque cada ejecución requiere una compilación.
    Esto nos lleva al segundo modo de ejecutar SQL dinámico dentro de un procedimiento almacenado.
     

    SQL dinámico con SP_EXECUTESQL
    El procedimiento 'sp_executesql’ puede utilizarse como alternativa a los procedimientos almacenados para ejecutar varias veces una instrucción de Transact-SQL si la única modificación es que cambian los valores de los parámetros. Como dicen los BOL, al permanecer constante la propia instrucción SQL y variar sólo los valores de los parámetros, es probable que el optimizador de consultas del SQL Server vuelva a utilizar el plan de ejecución que genera para la primera ejecución.
    El funcionamiento de sp_executesql es el siguiente:

    sp_executesql [@stmt =] stmt
    [
        {, [@params =]
    N'@parameter_name  data_type [,...n]' }
        {, [@param1 =] 'value1' [,...n] }
    ]

    Usar este procedimiento almacenado soluciona en gran parte los dos problemas que veíamos con la ejecución dinámica a través de EXEC.
    Por un lado lo único que se transmite a sp_executesql son los parámetros y eso evita la inyección de código, y por otro lado se puede reutilizar el plan de ejecución.
    Veamos un ejemplo de cómo utilizar este procedimiento.

    USE NorthWind
    DECLARE @sSQL nvarchar(1000)
    --la variabla que contiene la cadena a ejecutar debe ser unicode, por eso lo de nvarchar
    SET @sSQL = 'SELECT * FROM Products WHERE ProductName = @NombreProducto'
    EXEC sp_executesql @sSQL,
    N'@NombreProducto nvarchar(50)', @NombreProducto = 'chai'

    Como vemos el primer parámetro es la sentencia que queremos ejecutar, después viene declarada la variable que vamos a usar y por último le damos valor a esa variable.
    Seguro que se os ocurren un par de utilidades para sp_executesql. 
     

    Más sobre SP_EXECUTESQL
    Sp_executesql tiene unas cuantas peculiaridades que conviene tener en cuenta.
    Para empezar la ejecución de una sentencia a traves de sp_executesql se hace en un ámbito propio. Esto quiere decir que las variables declaradas fuera no se pueden utilizar, que las declaradas dentro no se pueden leer desde fuera, que podemos cambiar la base de datos (utilizar USE) en la que trabajar dentro del sp_executesql, crear tablas temporales en el nuevo ámbito, utilizar sentencias SET sin  hacer cambios en la configuración del procedimiento llamante, y por último aunque no menos importante que si se produce un error y se aborta la instrucción también se aborta el procedimiento en el que se está ejecutando.

    En cuanto a los permisos recordar algo muy importante. La sentencia SQL se ejecuta dentro del contexto de seguridad del usuario, no del procedimiento que llama a esa sentencia.

    Un ejemplo de cómo usar y como no usar SQL dinámico
    Para concluir vamos a ver un ejemplo donde podemos usar SQL dinámico.
    A veces tenemos que crear una sentencia que ordene una tabla según una columna que dependerá de algún parámetro que nos pasa el usuario. Eso lo podemos resolver utilizando un procedimiento almacenado y una sentencia como:

    CREATE PROCEDURE OrdenarPor @Columna varchar(50) AS
    DECLARE @sSQL varchar(50)
    SET @sSQL=’SELECT * FROM MiTabla ORDER BY ’ + @Columna
    EXEC @sSQL

    Esto está en la línea de todo lo que hemos estado diciendo.
    Es una solución sencilla pero que como no nos hemos cansado de repetir plantea varios problemas de seguridad y rendimiento. Así que ¿por que no pensamos un poco e intentamos crear un procedimiento almacenado que haga lo mismo?
    Creedme que pocas veces encontraremos una tarea que no se pueda resolver sin recurrir al SQL dinámico.
    Fijémonos en lo siguiente:

    CREATE PROCEDURE OrdenarPor @Columna varchar(50) AS
    SELECT * FROM   miTabla ORDER  BY
    CASE @Columna
                      WHEN 'columna1' THEN columna1
                      WHEN 'columna2' THEN columna2
                      WHEN 'columna3' THEN columna3
                   END

    Cierto que es un poco más complicado (se utiliza la función CASE), pero no hay inyección de código posible y una vez calculado el plan de ejecución se utilizará sin recompilar una y otra vez

    Como conclusión nos queda que el SQL dinámico es una herramienta potente pero peligrosa si no se trata con cuidado, y que la mayoría de las veces no necesitamos recurrir a ella porque siempre podemos encontrar otra solución.


    Valoración Media:
     



    WEBS RECOMENDADAS
    Programacion.com
    La Web del Programador
    Talleres del Web

    Artículos más Vistos
  • ¿Como manejar las fechas en Sql Server?
    Manejar las fechas en SQL Server es una de las preguntas más recurrentes en los foros. Maximiliano Damian nos explica como tratarlas

  • INSTALACION DE MYSQL 5 EN WINDOWS (I)
    MySQL es un servidor de bases de datos que cada vez tiene más adeptos. No nos da tantas facilidades ni funcionalidades como el SQL Server, pero es una optión a tener en cuenta...

  • SQL Dinámico: Exec y sp_executeSql
    La ejecución dinámica de instrucciones SQL es una potente herramienta a la que tarde o temprano tenemos que enfrentarnos.

  • Tablas temporales en el SQL Server
    En el mundo de las bases de datos es muy común la utilización de tablas temporales. Vamos a ver com hacer buen uso de ellas...

  • FAQ: Conexión con base de datos en ASP.NET con C#
    Vamos a ver de manera sencilla como mostrar el contenido de una tabla de Access en una página Web.

  •  

    Mensajes Nuevos

  • Academias ESPOL
    Enviado por paoyanez el Monday, December 29, 2008 (Her)

  • Unificacion de Datos
    Enviado por ? el Saturday, October 04, 2008 (Her)

  • qfopbmufuq
    Enviado por ? el Wednesday, October 01, 2008 (Her)

  • fpgaedac
    Enviado por ? el Sunday, September 28, 2008 (Her)

  • GENERACION DE TABLA EN PROCEDIMIENTOS
    Enviado por EDCOTA el Friday, September 26, 2008 (Her)



  •  

    Inicio   |   Help Desk   |   Foros SQL   |   Tutoriales SQL   |   Manuales SQL   |   Libros SQL   |   Enlaces   |   Programacion   |   Acerca de...

    Lenguaje SQL - Bases de Datos - SQL Server

    Diseño Paginas Web Codice DT

    Tarot por Telefono