Sentencia SQL if en la cláusula where para buscar en la base de datos
-
11-07-2019 - |
Pregunta
Estoy creando un procedimiento almacenado para devolver resultados de búsqueda donde algunos de los parámetros son opcionales.
Quiero una declaración "si" en mi cláusula where pero no puedo hacer que funcione. La cláusula where debe filtrar solo por los parámetros no nulos.
Aquí está la sp
ALTER PROCEDURE spVillaGet
-- Add the parameters for the stored procedure here
@accomodationFK int = null,
@regionFK int = null,
@arrivalDate datetime,
@numberOfNights int,
@sleeps int = null,
@priceFloor money = null,
@priceCeil money = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
select tblVillas.*, tblWeeklyPrices.price from tblVillas
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK
where
If @accomodationFK <> null then
accomodationTypeFK = @accomodationFK
@regionFK <> null Then
And regionFK = @regionFK
IF @sleeps <> null Then
And sleeps = @sleeps
IF @priceFloor <> null Then
And price >= @priceFloor And price <= @priceCeil
END
¿Alguna idea de cómo hacer esto?
Solución
select tblVillas.*, tblWeeklyPrices.price
from tblVillas
INNER JOIN tblWeeklyPrices on tblVillas.villaId = tblWeeklyPrices.villaFK
where (@accomodationFK IS null OR accomodationTypeFK = @accomodationFK)
AND (@regionFK IS null or regionFK = @regionFK)
AND (@sleeps IS null OR sleeps = @sleeps)
AND (@priceFloor IS null OR (price BETWEEN @priceFloor And @priceCeil))
Otros consejos
Hemos usado mucho COALESCE
aquí en el pasado para " cláusulas dinámicas WHERE " como si estuvieras hablando.
SELECT *
FROM vehicles
WHERE ([vin] LIKE COALESCE(@vin, [vin]) + '%' ESCAPE '\')
AND ([year] LIKE COALESCE(@year, [year]) + '%' ESCAPE '\')
AND ([make] LIKE COALESCE(@make, [make]) + '%' ESCAPE '\')
AND ([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\')
Sin embargo, surge un gran problema cuando desea filtrar opcionalmente una columna que también es anulable ... si los datos en la columna son null
para una fila dada Y el usuario no ingresó cualquier cosa para buscar esa columna (por lo que la entrada del usuario también es null
), entonces esa fila ni siquiera aparecerá en los resultados (que, si sus filtros son opcional, es un comportamiento de exclusión incorrecto).
Para compensar los campos anulables, termina teniendo que hacer un SQL de aspecto más desordenado de la siguiente manera:
SELECT *
FROM vehicles
WHERE (([vin] LIKE COALESCE(@vin, [vin]) + '%' ESCAPE '\')
OR (@vin IS NULL AND [vin] IS NULL))
AND (([year] LIKE COALESCE(@year, [year]) + '%' ESCAPE '\')
OR (@year IS NULL AND [year] IS NULL))
AND (([make] LIKE COALESCE(@make, [make]) + '%' ESCAPE '\')
OR (@make IS NULL AND [make] IS NULL))
AND (([model] LIKE COALESCE(@model, [model]) + '%' ESCAPE '\')
OR (@model IS NULL AND [model] IS NULL))
Para que lo entiendas, IF es un código de procedimiento en T-SQl. No se puede usar en una declaración de inserción / actualización / eliminación / selección, solo se puede usar para determinar cuál de las dos declaraciones desea ejecutar. Cuando necesite diferentes posibilidades dentro de una declaración, puede hacer lo anterior o usar una declaración CASE.
También puede usar la función IsNull o Coalesce
Where accomodationTypeFK = IsNull(@accomodationFK, accomodationTypeFK)
And regionFK = Coalesce(@regionFK,regionFK)
And sleeps = IsNull(@sleeps,sleeps )
And price Between IsNull(@priceFloor, Price) And IsNull(priceCeil, Price)
Esto hace lo mismo que la sugerencia anterior de Michael ...
IsNull () y Coalesce () funcionan más o menos de la misma manera, devuelven el primer argumento no nulo en la lista, excepto que iSNull solo permite 2 argumentos y Coalesce puede tomar cualquier número ...
http: / /blogs.msdn.com/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx
Intente colocar su declaración IF alrededor de toda la declaración SQL. Eso significa que tendrá una instrucción SQL para cada condición. Eso funcionó para mí.