2012-01-27 3 views
1

현재 내 쿼리의 WHERE 절에 다음 SQL 문을 사용하는 Java로 준비된 명령문이 있지만이 함수를 제한적으로 다시 작성하려고합니다 사용자 매개 변수가 전달되어 더 효율적으로 만들 수 있습니다.null 검색을 포함하는 where 절의 함수 사용

(
    (USER_PARAM2 IS NULL AND 
    (COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR 
     (nvl(USER_PARAM1, COLUMN_NAME) IS NULL) 
    ) 
) 
    OR 
    (USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL) 
) 

USER_PARAM1 및 USER_PARAM2는 사용자가 준비된 명령문에 전달됩니다. USER_PARAM1은 애플리케이션 사용자가이 특정 COLUMN_NAME을 (를) 검색하려고하는 것을 나타냅니다. 사용자가이 매개 변수를 포함하지 않으면 기본적으로 NULL이됩니다. USER_PARAM2는 사용자가이 COLUMN_NAME에서 NULL 값만 검색하도록 요청할 수있는 방법이었습니다. 또한 사용자가 전달한 경우 USER_PARAM2를 'true'로 설정하거나 사용자가 지정하지 않은 경우 NULL을 설정하는 일부 서버 로직이 있습니다.

USER_PARAM2가 선언 된 경우 NULL의 COLUMN_NAME 값만 반환됩니다. USER_PARAM2가 선언되지 않고 USER_PARAM1이 선언 된 경우 COLUMN_NAME = USER_PARAM1 만 반환됩니다. 사용자 매개 변수가 선언되지 않으면 모든 행이 반환됩니다.

아무도 나를 도울 수 없습니까? 사전에 감사합니다 ...

편집 : 그냥 명확하게이 내 현재의 쿼리 (.. 다른 WHERE 절 문없이)

SELECT * 
FROM TABLE_NAME 
WHERE (
    (USER_PARAM2 IS NULL AND 
    (COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR 
     (nvl(USER_PARAM1, COLUMN_NAME) IS NULL) 
    ) 
) 
    OR 
    (USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL) 
) 

보이는 ... 이것은 어디 것입니다 방법입니다 ...에 도착 좋아 EDIT # 2

SELECT * 
FROM TABLE_NAME 
WHERE customSearchFunction(USER_PARAM1, USER_PARAM2, COLUMN_NAME) 

: OK, 그래서 다른 동료가 이것 좀 도와 ...

,414,325,321

0 ...이 .. 내 초기 시험에서

SELECT * 
FROM TABLE_NAME 
WHERE 1=searchNumber(USER_PARAM1, USER_PARAM2, COLUMN_NAME); 

을 작동하는 것 같다 ... 나는 그것으로 가지고있는 유일한 문제는 내가 시작 복잡한 SQL 문 대 1) 가능한 성능 문제 될 것 . 2) 각 데이터 유형에 대해 비슷한 기능을 만들어야합니다. 그러나 후자는 나를 위해 덜 중요한 문제입니다. 코드/쿼리 청결 성능을 압도 기능 기반의 접근 방식을 사용하는 동안

편집 # 3 2012.02.01

그래서 우리는, 내가 아래에 선택한 솔루션과 함께가는 끝났다. 우리는 함수 기반 접근법이 순수 SQL을 사용하는 것보다 약 6 배 더 나 빠졌음을 발견했습니다.

많은 분들께 감사드립니다.

편집 #하는 2012년 2월 14일

4 그래서 찾고 다시 나는 @ danihp의 솔루션의 선명도와 @ 앨런의 솔루션을 가상 테이블 개념을 적용하는 것은 명확성과 성능면에서 아주 좋은 전반적인 솔루션을 제공 것으로 나타났습니다. 여기 내가 지금 무엇을 가지고있다

WITH params AS (SELECT user_param1 AS param, user_param2 AS param_nullsOnly FROM DUAL) 
SELECT * 
FROM table_name, params p 
WHERE (nvl(p.param_nullsOnly, p.param) IS NULL     --1) 
     OR p.param_nullsOnly IS NOT NULL AND column_name IS NULL --2) 
     OR p.param IS NOT NULL AND column_name = p.param   --3) 
     ) 
-- 1) Test if all rows should be returned 
-- 2) Test if only NULL values should be returned 
-- 3) Test if param equals the column value 

제안이나 의견에 다시 한 번 감사드립니다!

+0

왜 함수로 변경합니까? 네이티브 SQL은 지저분 해 보이는 것처럼 보이지만 분명히 잘 수행됩니다. –

+0

정말로 함수를 원하면 "customSearchFunction"이 varchar2 값 (예 : S/N)을 반환해야합니다. 그리고 당신의 위치는 어디입니까? customSearchFunction (USER_PARAM1, USER_PARAM2, COLUMN_NAME) = 'S' –

+1

명시된대로 함수를 사용하면 성명을 평가할 때 전체 테이블 스캔을 강요 할 수 있습니다. 작은 테이블 (또는 작은 테이블의 조인)이라면 이것은 중요하지 않을 수도 있지만 큰 테이블 인 경우에는 성능이 많이 요구 될 수 있습니다. YMMV. –

답변

2

공통 테이블 표현식을 사용하여 매개 변수를 한 번만 전달하고 필요한만큼 여러 번 참조 할 수있는 간단한 방법이 있습니다.

WITH params AS (SELECT user_param1 AS up1, user_param2 AS up2 FROM DUAL) 
SELECT * 
FROM table_name, params p 
WHERE ((p.up2 IS NULL 
     AND (column_name = NVL(p.up1, column_name) 
       OR (NVL(p.up1, column_name) IS NULL))) 
     OR (p.up2 IS NOT NULL AND column_name IS NULL)) 

사실상 하나의 행으로 채워지는 매개 변수 인 가상 테이블을 만듭니다.

편리하게도 모든 매개 변수가 동일한 위치에서 수집되고 임의의 순서로 지정할 수 있습니다 (쿼리에서 자연스럽게 나타나는 순서와 반대).

함수 기반 접근 방식에 비해 몇 가지 큰 이점이 있습니다. 첫째, 인덱스의 사용을 막을 수는 없습니다 (@Bob Jarvis가 지적한 바와 같이). 둘째, 이는 쿼리의 로직을 함수에 숨기지 않고 쿼리에 유지합니다.

+0

감사합니다. 속도의 조합과 여분의 매개 변수 제거에 대한이 접근법을 정말 좋아합니다. – hypno7oad

2

내 방식보다 성능이 있는지 나도 몰라,하지만 가장 가독성이 있습니다

where 
(P_ALL_RESULTS is not null 
    OR 
    P_ONLY_NULLS is not null AND COLUMN_NAME IS NULL 
    OR 
    P_USE_P1 is not null AND COLUMN_NAME = USER_PARAM1 
) 

면책 조항 :

당신이 같은 쿼리를 다시 작성할 수 있습니다 쿼리 2 개 추가 항목의 매개 변수를 보내기 전에 대답 OP 질문 명확화

+1

마지막 조건을 읽어야합니다. P_USE_P1은 null이 아니며 COLUMN_NAME = USER_PARAM1 –

+0

@BD, 고정, 감사합니다. – danihp

+0

면책 조항 : OP 질문 명확화 전에 답하십시오. – danihp