2013-07-08 6 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에만 영향을 미치며 다른 결과는 반환되지 않으므로 모든 행이 반환됩니다.

는이 문제를 해결하려면 초기 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' 

모든 추가 기준은 당신의 처음 항상 true (1=1) WHERE 절에 추가됩니다,이 제대로 결과를 필터링합니다.

참고 : 현재 구현은 SQL Injection에 취약합니다.


편집 : 같은 테이블에, 예상과 다른되지 하나가 작동 City 이후 및 State, 나는이 예상대로 작동하지 않는 당신의 LEFT OUTER JOIN 관련이 있다고 생각하지 않습니다.

대신 나는 에 대해 수행되는 트리밍과 관련이 있지만 City에는 적용되지 않는다고 생각합니다.

먼저 LTRIM, RTRIM의 값을 확인하기 전에 아무 것도하지 않습니다. IS NOT NULL입니다. NULL이거나 그렇지 않으면 트리밍으로 변경되지 않습니다.

다음으로 동적 SQL에서 TRIM 함수를 호출합니다. 이것은 내장 된 T-SQL 함수가 아니므로 TRIM이라는 사용자 정의 함수가 없으면 실제로 런타임 오류가 발생합니다.

+0

+1 : 이것은 'r'([resource]) 이외의 테이블을 참조하는'WHERE' 절에 추가 된 조건이 해당 LEFT OUTER JOIN을 효과적으로 'IN JOIN'으로 변환한다는 것을 제외하고는 정확합니다. . – RBarryYoung

+0

그게 내가 가지고있는 새로운 문제 일 수도 있습니다. 도시에서만 검색 할 때 여전히 정확한 답을줍니다. 그러나 내가 국가 만 검색 할 때. 쿼리는 올바른 상태가 아닌 경우에도 db의 모든 행을 반환합니다. 상태는 ASP 형식의 드롭 다운 목록에서옵니다. 이 문제를 해결하는 방법을 알고 있습니까? – JerseyGirl1201

+0

@RBarryYoung 좋은 지적이지만 추가 조건이 필터로 작용하기 때문에 'LEFT OUTER JOIN'을 'IN JOIN'으로 변환하면 예상되는 동작이 될 것입니다. –

관련 문제