2013-07-08 143 views
1

我正在尝试编写动态查询。搜索标准将来自ASP页面,并将 传递给SQL Server 2005 Express数据库中的存储过程。搜索不会给出任何错误,但会返回数据库中的所有数据,并且不会基于变量进行过滤。有人请帮忙?动态查询无法正常工作

我在这里张贴的存储过程:

set ANSI_NULLS ON 
set QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[spSearchResource] 
    @ResourceID int, 
    @Name varchar(75), 
    @City varchar(75), 
    @State varchar(2), 
    @County varchar(30), 
    @Specialty varchar(100), 
    @Zip varchar(5), 
    @English bit, 
    @Spanish bit, 
    @French bit, 
    @Italian bit, 
    @Chinese bit, 
    @Japanese bit, 
    @GenderType varchar(8), 
    @Within int, 
    @Children bit, 
    @Adolescents bit, 
    @Adults bit, 
    @Geriatrics bit, 
    @Insurance varchar(50) 
AS 
BEGIN 

    DECLARE @strSql varchar(4000); 

    SET @strSql = 'select r.resourceid, r.flag, r.note, r.Name, r.ContactName, r.Website, r.Email, >r.GenderType, loc.Street, loc.city, loc.State, loc.Zip, loc.County,phone.areacode, 
       phone.phonenum,phone.extension,spec.specialty, 
    ins.insurance,pop.children,pop.Adolescents,  
    pop.adults,pop.geriatrics,lan.english,lan.spanish,lan.french,lan.italian,lan.chinese,lan.japanese 
    from resource r left outer join resourcelocation loc on (r.resourceid = loc.resourceid) 
    left outer join resourcephone phone on (r.resourceid = phone.resourceid) 
    left outer join resourceinsurance ins on (r.resourceid = ins.resourceid) 
    left outer join resourcepopulation pop on (r.resourceid = pop.resourceid) 
    left outer join resourcespecialty spec on (r.resourceid = spec.resourceid) 
    left outer join resourcelanguage lan on (r.resourceid = lan.resourceid) ' 

     if (@ResourceID is not null) 
      SET @strSql = @strSql + 'and r.resourceid = ' + (CONVERT(VARCHAR(10),@ResourceID)) 

     if (@Name is not null) 
      SET @strSql = @strSql + 'and r.Name like '+''''+ @Name+'%''' 

     if (@City is not null) 
      SET @strSql = @strSql + 'and loc.city like '+''''+ @City+'%''' 

     if (ltrim(rtrim(@State)) is not null) 
      SET @strSql = @strSql + 'and loc.State = trim(@State) ' 

     if (ltrim(rtrim(@Zip)) is not null) 
      SET @strSql = @strSql + 'and loc.Zip = trim(@Zip) ' 

     if (ltrim(rtrim(@County)) is not null) 
      SET @strSql = @strSql + 'and loc.County like trim(@County) ' 

     if (ltrim(rtrim(@specialty)) is not null) 
      SET @strSql = @strSql + 'and spec.specialty = trim(@spcialty) ' 

     if (ltrim(rtrim(@insurance)) is not null) 
      SET @strSql = @strSql + 'and ins.insurance = trim(@insurance) ' 

     if (@English = 1) 
      SET @strSql = @strSql + 'and lan.english = @English' 

     if (@Spanish = 1) 
      SET @strSql = @strSql + 'and lan.spanish = @Spanish ' 

     if (@French = 1) 
      SET @strSql = @strSql + 'and lan.french = @French ' 

     if (@Italian = 1) 
      SET @strSql = @strSql + 'and lan.italian = @Italian ' 

     if (@Chinese = 1) 
      SET @strSql = @strSql + 'and lan.Chinese = @Chinese ' 

     if (@Japanese = 1) 
      SET @strSql = @strSql + 'and lan.japanese = @Japanese ' 

     if (ltrim(rtrim(@GenderType)) != 0) 
      SET @strSql = @strSql + 'and r.GenderType like trim(@GenderType) ' 

     if (@children = 1) 
      SET @strSql = @strSql + 'and pop.children = @children ' 

     if (@Adolescents = 1) 
      SET @strSql = @strSql + 'and pop.Adolescents = @Adolescents ' 

     if (@adults = 1) 
      SET @strSql = @strSql + 'and pop.adults = @adults ' 

     if (@geriatrics = 1) 
      SET @strSql = @strSql + 'and pop.geriatrics = @geriatrics ' 

     print @strSql; 
     execute (@strSql); 
    END 
+0

那么什么打印时,它打印字符串? – JNK

回答

2

的问题是,你的过滤器不会被添加到WHERE条款,而是被添加作为条件你最后LEFT OUTER JOIN。当条件不符合时,它只会影响最后一个JOIN,而不会影响其他结果,这就是为什么您要返回所有行。

为了解决这个问题,添加一个WHERE下列条款向您最初的SQL字符串:

SET @strSql = 'select r.resourceid, r.flag, r.note, r.Name, r.ContactName, 
... 
left outer join resourcelanguage lan on (r.resourceid = lan.resourceid) 
where 1 = 1' 

任何附加标准将被添加到您最初总是正确的(1=1WHERE条款,这应该正确地过滤结果。

注意:您当前的实现容易受到SQL Injection的影响。


编辑: 由于CityState在同一个表,一个按预期工作,而不是其他的,我不认为这是关系到你的LEFT OUTER JOIN无法按预期工作。

相反,我认为这与修整有关,这是针对State而不是针对City完成的。

首先,它不会对LTRIM,RTRIM做任何事情,然后检查它是否为IS NOT NULL。要么是NULL要么它不是,修剪不会改变这一点。

接下来,在您的动态SQL中,您可以调用TRIM函数。这不是一个内置的T-SQL函数,所以除非你有自己的用户定义函数TRIM,否则这应该会给你一个运行时错误。

+0

+1:除了添加到引用'r'([resource])以外的任何表的'WHERE'子句的任何条件将有效地将相应的'LEFT OUTER JOIN'变为'INNER JOIN' 。 – RBarryYoung

+0

这可能是我遇到的新问题,当我只通过城市搜索时,它仍然给我正确的答案。但是,当我只搜索状态。查询返回db中的所有行,即使它不是正确的状态。状态来自asp窗体中的下拉列表。你知道如何解决这个问题吗? – JerseyGirl1201

+0

@RBarryYoung好点,但由于额外的条件作为过滤器,我的猜测是,将'LEFT OUTER JOIN'转换为'INNER JOIN'将是预期的行为... –