Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » SQL Server »

Procedimiento con SQL dinámico

Estas en el tema de Procedimiento con SQL dinámico en el foro de SQL Server en Foros del Web. Hola a tod@s: Quería ir construyendo las condiciones del WHERE de la consulta SELECT que lleva uno de mis procedimientos, según los valores que llegasen. ...
  #1 (permalink)  
Antiguo 14/09/2007, 02:08
Avatar de zacktagnan  
Fecha de Ingreso: abril-2005
Mensajes: 501
Antigüedad: 19 años
Puntos: 3
Procedimiento con SQL dinámico

Hola a tod@s:

Quería ir construyendo las condiciones del WHERE de la consulta SELECT que lleva uno de mis procedimientos, según los valores que llegasen.
Y según ví en lo que encontré en la Web y en este foro, esto se hace con el llamado SQL dinámico.

Según lo visto llegué a hacerlo de dos maneras, las dos probadas a través del SQL Server, como cualquier otra consulta de prueba. Y funcionaban bien.
Pero luego, después de armar el Procedimiento y ejecutar la búsqueda según los parámetros elegidos, a través de la página web, sólo una de las formas funcionaba.

De manera extraña, ahora he vuelto a probar y funcionan las dos: la que está usando el 'sp_executesql' y la que no lo lleva (que es la que de primeras no funcionaba).

Mi pregunta iba a ser por qué no lo hacía la que no funcionaba pero ahora aprovecharé el tema lanzado para preguntar sobre eso de la seguridad en este tipo de consultas, sobre eso de la inyección de código malicioso.

¿Sería mejor usar la que no lleva el 'sp_executesql'? Sino, ¿una y otra son igual de efectivas ó una de ellas tiene mejor resultado?, bueno no sé es la primera vez que hago esto en ASP.NET...

Bueno, estas son las dos formas como me queda el procedimiento:

* con el 'sp_executesql' *

Código:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER PROCEDURE [dbo].[spSelec_AvisoCallCtr]
	@avis_fecha_ini DATETIME,
	@avis_fecha_fin DATETIME,
	@avis_empl INT,
	@avis_estccrep TINYINT,
	@avis_filtro NVARCHAR(250)

AS

SELECT @avis_empl = ISNULL(@avis_empl, 0)
SELECT @avis_estccrep = ISNULL(@avis_estccrep, 0)

-- SIEMPRE VIENE UNA FECHA DE INICIO Y OTRA DE FIN
-- EL PARÁMETRO @avis_empl SERÁ:
-- * 0, PARA TODOS U OTRO NÚMERO PARA UNO DETERMINADO
-- EL PARÁMETRO @avis_estccrep SERÁ:
-- * 0, PARA CUALQUIERA U OTRO NÚMERO PARA UNO DETERMINADO
-- EL PARÁMETRO @avis_filtro SERÁ:
-- * esnulo, SI NO SE INDICA NADA Ó EL TÉRMINO A CONSIDERAR

DECLARE @WHERE NVARCHAR(1000)
DECLARE @SQL_LARGO NVARCHAR(2000)
SET @WHERE = ' WHERE avis_fecha BETWEEN @avis_fecha_ini AND @avis_fecha_fin'

  IF @avis_empl <> 0
     SET @WHERE = @WHERE + ' AND avis_empl = @avis_empl'

  IF @avis_estccrep <> 0
     SET @WHERE = @WHERE + ' AND avis_estccrep = @avis_estccrep'

  IF @avis_filtro <> 'esnulo'
     SET @WHERE = @WHERE + ' AND (avis_asunto LIKE + ''%' + @avis_filtro + '%''' + ' OR avis_descrip LIKE + ''%' + @avis_filtro + '%''' + ' OR avis_clienom LIKE + ''%' + @avis_filtro + '%''' + ' OR avis_contactoclie LIKE + ''%' + @avis_filtro + '%'')'

SET @SQL_LARGO = 'SELECT avis_id, avis_fecha,
					 ISNULL(CONVERT(NVARCHAR,avis_clieid),''0'') AS avis_clieid,
					 avis_clienom, avis_asunto,
					 estccrep_nom, nombre AS empl_nom_completo
				FROM
					EMPLEADOS INNER JOIN (
					AVISOS INNER JOIN ESTADOS_CCREP
					ON AVISOS.avis_estccrep = ESTADOS_CCREP.estccrep_id)
					ON EMPLEADOS.codigo = AVISOS.avis_empl'
				+ @WHERE +
				' ORDER BY
					avis_fecha DESC, avis_clienom, estccrep_nom, empl_nom_completo'

exec sp_executesql @SQL_LARGO, N'@avis_fecha_ini DATETIME, @avis_fecha_fin DATETIME, @avis_empl INT, @avis_estccrep TINYINT, @avis_filtro NVARCHAR(250)', @avis_fecha_ini, @avis_fecha_fin, @avis_empl, @avis_estccrep, @avis_filtro

* sin el 'sp_executesql' *

Código:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER PROCEDURE [dbo].[spSelec_AvisoCallCtr]
	@avis_fecha_ini DATETIME,
	@avis_fecha_fin DATETIME,
	@avis_empl INT,
	@avis_estccrep TINYINT,
	@avis_filtro NVARCHAR(250)

AS

SELECT @avis_empl = ISNULL(@avis_empl, 0)
SELECT @avis_estccrep = ISNULL(@avis_estccrep, 0)

-- SIEMPRE VIENE UNA FECHA DE INICIO Y OTRA DE FIN
-- EL PARÁMETRO @avis_empl SERÁ:
-- * 0, PARA TODOS U OTRO NÚMERO PARA UNO DETERMINADO
-- EL PARÁMETRO @avis_estccrep SERÁ:
-- * 0, PARA CUALQUIERA U OTRO NÚMERO PARA UNO DETERMINADO
-- EL PARÁMETRO @avis_filtro SERÁ:
-- * esnulo, SI NO SE INDICA NADA Ó EL TÉRMINO A CONSIDERAR

SELECT avis_id, avis_fecha,
	 ISNULL(CONVERT(NVARCHAR,avis_clieid),'0') AS avis_clieid,
	 avis_clienom, avis_asunto,
	 estccrep_nom, nombre AS empl_nom_completo
FROM
	EMPLEADOS INNER JOIN (
	AVISOS INNER JOIN ESTADOS_CCREP
	ON AVISOS.avis_estccrep = ESTADOS_CCREP.estccrep_id)
	ON EMPLEADOS.codigo = AVISOS.avis_empl
WHERE avis_fecha BETWEEN @avis_fecha_ini AND @avis_fecha_fin
AND ( @avis_empl = 0 Or avis_empl = @avis_empl )
AND ( @avis_estccrep = 0 Or avis_estccrep = @avis_estccrep )
AND ( @avis_filtro = 'esnulo'
	Or (avis_asunto LIKE '%' + @avis_filtro + '%'
	OR avis_descrip LIKE '%' + @avis_filtro + '%'
	OR avis_clienom LIKE '%' + @avis_filtro + '%'
	OR avis_contactoclie LIKE '%' + @avis_filtro + '%'))
ORDER BY
	avis_fecha DESC, avis_clienom, estccrep_nom, empl_nom_completo
__________________
Saludos,

zacktagnan.
=================================================

Última edición por zacktagnan; 14/09/2007 a las 08:50
  #2 (permalink)  
Antiguo 14/09/2007, 08:44
Avatar de Andres95
Colaborador
 
Fecha de Ingreso: diciembre-2004
Mensajes: 1.802
Antigüedad: 19 años, 4 meses
Puntos: 38
Re: Procedimiento con SQL dinámico

- Yo no utilizaria sql dinamico para sentencia que tienes, es mejor el select que ya armaste.
- El sp_executesql esta mal empleado, no es necesario que envies ningun parametro ya que todos los armaste en el string.
- ¿Que error te marca el select? o simplemente no te trae valores?, danos mas detalles acerca de la info existente en la bd y la llamada al procedimiento en el momento en el que no funciona, para que te puedan ayudar mejor.

saludos!
__________________
La sencillez y naturalidad son el supremo y último fin de la cultura...
--
MCTS : SQL Server 2008, .NET Framework 3.5, ASP.NET Applications.
  #3 (permalink)  
Antiguo 14/09/2007, 09:03
Avatar de zacktagnan  
Fecha de Ingreso: abril-2005
Mensajes: 501
Antigüedad: 19 años
Puntos: 3
Re: Procedimiento con SQL dinámico

Cómo dije en el 1º mensaje...

Cita:
De manera extraña, ahora he vuelto a probar y funcionan las dos: la que está usando el 'sp_executesql' y la que no lo lleva (que es la que de primeras no funcionaba).
Es decir, que estaba escribiendo para plantear el problema y justo antes de terminar de escribir, me dió por probar de nuevo. Y va y resulta que lo que no me funcionaba el día anterior ahora si lo hacía.

Y ya que estaba planteando la cuestión pues lo deje para preguntar por eso de la seguridad y todo lo demás.

Ya veo que tu prefieres la consulta con el SELECT nada más, sin el sp_executesql. Para armar esta me base entre otras cosas en otro mensaje en el que tu participabas.

Y la forma con el sp_executesql, también de otro mensaje que también necesitaban ponerlo en un procedimiento que recibía parámetros que podían ser mandados ó no según lo que quisiera el usuario...

Cita:
¿Que error te marca el select? o simplemente no te trae valores?
Cuando dije que no funcionaba una de las formas que expongo, no puntualice como tu lo has hecho. Y si, la verdad es que no me daba error sino que, de manera extraña, una consulta que tenía que dar resultados no los daba.
Y ¿por qué? ... Pues no lo sé.

Si tu tienes la explicación, ya me dirás...
__________________
Saludos,

zacktagnan.
=================================================
  #4 (permalink)  
Antiguo 14/09/2007, 09:47
Avatar de Andres95
Colaborador
 
Fecha de Ingreso: diciembre-2004
Mensajes: 1.802
Antigüedad: 19 años, 4 meses
Puntos: 38
Re: Procedimiento con SQL dinámico

Ok, zacktagnan.

Es importante que "puntualices" porque las preguntas especificas
son resueltas de forma mas rapida, uno de los factores es el tiempo que hay que invertir para imaginar el (los) escenario(s) que se te pueden presentar.

Por otro lado, si es mas seguro utilizar procedimientos sin sql dinamico o bien utilizar sp_executesql (ademas de seguro por performance) con parametros en lugar del sql dinamico. Y como te comentaba, la forma que utilizaste para armar el query es como se haria con un Execute (sqlString) -- la forma mas insegura.

Y bueno como lo veo, en tu caso es mejor es utilizar el select normal.


saludos
__________________
La sencillez y naturalidad son el supremo y último fin de la cultura...
--
MCTS : SQL Server 2008, .NET Framework 3.5, ASP.NET Applications.

Última edición por Andres95; 14/09/2007 a las 10:07
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 05:40.