2010-05-09 3 views
3

SQL Server 2008 데이터베이스의 테이블에 대해 쿼리를 실행하려고합니다. 5 개의 int 매개 변수를 사용하는 저장 프로 시저가 있습니다. 현재 내 매개 변수는 다음과 같이 정의됩니다.SQL Server 2008의 조건부 WHERE 절

@memberType int, 
@color int, 
@preference int, 
@groupNumber int, 
@departmentNumber int 

이 절차는 각 매개 변수에 대해 -1 이상이 전달됩니다. -1 값은 WHERE 절이 조인/절에서 해당 매개 변수를 고려하지 않아야 함을 의미합니다. 매개 변수의 값이 -1보다 크면 WHERE 절의 값을 고려해야합니다. IF-ELSE 문을 사용하지 않는 편이 좋을 것입니다.

이 질문은 here입니다. 그러나, 그것은 나를 위해 작동하지 않았다. 왜 내 테이블의 각 열에 NULL 값을 가질 수 있기 때문에 그 이유가 있다고 생각합니다. 누군가 다섯 번째 대답에서이 시나리오를 지적했습니다. 그것은 저에게 일어나는 것처럼 보입니다.

내 질문에 매끄러운 접근법이 있습니까? 아니면 그냥 (내가하지 희망 :()를 무력해야합니까

감사합니다

답변

4

내가 과거에 이런 짓을했습니다.!

SELECT 
    ..... 
FROM 
    dbo.SOMETABLE AS T 
WHERE 
    (T.memberType = @memberType OR @memberType = -1) 
    AND (T.color = @color OR @color = -1) 
    AND (T.preference = @preference OR @preference = -1) 
    AND (T.groupNumber = @groupNumber OR @groupNumber = -1) 
    AND (T.departmentNumber = @departmentNumber OR @departmentNumber = -1) 

그러나 일반적으로, . 나는 걱정하지 않는다 나의 매개 변수가 NULL입니다 다음 쿼리가된다 :.

SELECT 
    ..... 
    FROM 
    dbo.SOMETABLE AS T 
    WHERE 
    (T.memberType = @memberType OR @memberType IS NULL) 
    AND (T.color = @color OR @color IS NULL) 
    AND (T.preference = @preference OR @preference IS NULL) 
    AND (T.groupNumber = @groupNumber OR @groupNumber IS NULL) 
    AND (T.departmentNumber = @departmentNumber OR @departmentNumber IS NULL) 
+0

'COALESCE' (NULL의 경우)를 사용하는 것보다 빠릅니다. – crush

1
내가 동적 SQL을 제안

- 귀하가받는 매개 변수를 기반으로 문자열 (VARCHAR) 같이 쿼리를 생성 추가 항목 만 티 o 당신이 정말로 필요로하는 where 절. 그런 다음 sp_executesql을 사용하여 실행하십시오. 동적 SQL은 일반적으로 사전 컴파일 된 SQL보다 효율적이지 않지만, 귀하의 경우에는 올바른 방법으로 생각됩니다. 쿼리 계획을 재사용 할 때 최적의 결과를 얻을 수 있도록 쿼리를 매개 변수화해야합니다.

+0

필자는 항상 저장 프로 시저에서 동적 SQL을 발견했습니다. 내가 사용한 적이있는 유일한 시간은 특정 openquery 상황입니다. – BradBrening

+0

나는 일반적으로 사용자가 다양한 필터링 옵션을 가지고있는 검색 페이지와 같이 사용합니다. 몇 번이나 'where'절에 몇 가지 간단한 문제가 아닌 'from'절에 추가 테이블이 필요할 수도 있습니다. 이러한 경우 동적 SQL을 사용하는 것이 모든 기반을 포괄하는 단일 쿼리보다 더 효율적일 수 있습니다. – Ray

3

스레드가 오래되었음을 알고 있지만 적절한 결정을 내리는 데 도움이 될 수있는 몇 가지 추가 세부 정보가 있습니다. 여러 솔루션이 있습니다

1)

SELECT ... 
FROM ... 
WHERE 
    (T.memberType = @memberType OR @memberType = -1) 
    AND (T.color = @color OR @color = -1) 
    AND (T.preference = @preference OR @preference = -1) 
    AND (T.groupNumber = @groupNumber OR @groupNumber = -1) 
    AND (T.departmentNumber = @departmentNumber OR @departmentNumber = -1) 

2)

3

SELECT ... 
FROM ... 
WHERE 
    (T.memberType = @memberType OR @memberType IS NULL) 
    AND (T.color = @color OR @color IS NULL) 
    AND (T.preference = @preference OR @preference IS NULL) 
    AND (T.groupNumber = @groupNumber OR @groupNumber IS NULL) 
    AND (T.departmentNumber = @departmentNumber OR @departmentNumber IS NULL) 
)이 동적으로

4) 동적 DML을 생성하고 sp_executesql을을 사용하여 문 대한 EXECUTE DML을 생성하고 사용

옵션 1과 2는 거의 동일합니다. -1보다 IS NULL을 사용하지만 대부분의 경우와 마찬가지로 상황에 따라 다릅니다. 이러한 옵션의 단점 중 하나는 저장 프로 시저를 처음 실행하면 모든 후속 호출에서 다시 사용할 쿼리 계획이 생성된다는 것입니다. 매개 변수의 값이 변경되면 (특히 무시할 값) 초기 쿼리 계획이 더 이상 최적의 계획이 아닐 수도 있습니다.이 문제를 해결하려면 WITH RECOMPILE 옵션을 사용합니다 (호출 할 때마다 프로 시저가 다시 컴파일된다는 경고가 표시됨).

옵션 3과 4는 더 많은 데이터가 테이블에 추가되거나 WHERE 절에 더 많은 기준이 추가 될 때 더 잘 수행됩니다. 그러나 이러한 옵션은 저장 프로 시저를 작성하고 잠재적 SQL 주입 취약점을 최소화하기 위해 입력 매개 변수의 유효성 검사를 더 많이 수행해야합니다.옵션 4는 옵션 3보다 좋으며 동적으로 생성 된 SQL에보다 효과적인 쿼리 계획 재사용을 유도하는 매개 변수 이름이 포함되어 있기 때문에 어떤면에서는 다소 단순합니다. 동적으로 생성 된 SQL의 또 다른 단점은 프로 시저가 WITH EXECUTE AS ... 절로 정의되지 않은 경우 내장 프로 시저를 호출하는 사용자가 기본 테이블/뷰에 대한 모든 필요한 권한을 가져야한다는 것입니다.

결국 나는 일반적으로 sp_executesql을 사용하여 동적으로 생성 된 SQL을 사용하여 최상의 수행 쿼리를 생성합니다.