2008-11-25 104 views
14

我正在创建一个存储过程以返回其中某些参数是可选的搜索结果。SQL if语句用于搜索数据库的where子句

我想要一个“if语句”在我的其中子句,但不能得到它的工作。 其中子句应该仅通过非空参数进行过滤。

这里的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 

任何想法如何做到这一点?

回答

25
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)) 
+0

感谢您的帮助,但数据库中的值不为空。如果为其中一个参数传递null,我想跳过where子句的那一部分 – mancmanomyst 2008-11-25 13:51:52

+4

为什么这是有效的:如果@var为null,那么整行就是true,而不管行的其余部分如何(因此忽略和未过滤)。如果它不为null,则该行为false *除非* ColVar = @ var,因此应用过滤器。我第一次读这种过滤器风格但现在到处都使用它,我感到困惑。 – 2008-11-25 13:52:20

+0

mancmanomyst.myopenid.com:就是这样。我建议制作一张真相表 - 开始时并不直观。 – 2008-11-25 13:53:08

0

您还可以使用ISNULL或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) 

这做同样的事情如上迈克尔的建议...

ISNULL(),并凝聚()工作或多或少同样,它们返回列表中的第一个非空参数,但iSNull只允许2个参数,并且Coalesce可以采用任何数字...

http://blogs.msdn.com/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx

0

过去我们在这里使用了很多COALESCE,就像你谈论的那样,“dynamic WHERE clauses”。

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 '\') 

一个大问题出现,虽然,当你想有选择地过滤的列也可为空......如果列中的数据是null对于给定的行和用户没有输入任何搜索(所以用户输入也是null),那么行甚至不会显示在结果(如果您的过滤器是可选的,是不正确的排他行为)。

为了弥补可能为空的字段,你最终不得不做梅西尔的寻找SQL就像这样:

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)) 
0

只要你明白,如果在T-SQL程序代码。它不能用于插入/更新/删除/选择语句,它只能用于确定要运行的两个语句中的哪一个。当你在一个陈述中需要不同的可能性时,你可以像上面那样做,或者使用CASE陈述。

-2

尝试将IF语句放在整个SQL语句中。这意味着每个条件都会有一个SQL语句。这对我有效。