动态查询无法正常工作

时间:2013-07-08 15:01:37

标签: sql stored-procedures dynamic sql-server-2005-express

我正在尝试编写动态查询。搜索条件将来自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

1 个答案:

答案 0 :(得分:2)

问题是您的过滤器未添加到WHERE子句中,而是作为条件添加到您的上一个LEFT OUTER JOIN。如果未满足条件,则仅影响最后JOIN,而不影响其他结果,这就是您返回所有行的原因。

要解决此问题,请在初始SQL字符串后添加WHERE子句:

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的攻击。<​​/ p>


编辑: 由于CityState位于同一个表中,并且其中一个按预期工作而不是另一个,我认为这与您的LEFT OUTER JOIN无法正常工作有关。

相反,我认为它与针对State但不针对City的修剪有关。

首先,在检查LTRIM之前,它对RTRIMIS NOT NULL没有任何作用。无论是NULL还是不是,修剪都不会改变它。

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