프로시저 동적쿼리 1 26 1,308

by 뀽 [2017.01.11 15:08:14]


쿼리.PNG (18,998Bytes)
값.PNG (2,763Bytes)

프로시저를 동적으로 작성하려고 하는데 쿼리는 동일한데 매개변수가 없거나 1개이거나 2개인 경우가 있는데 

이경우 처리할수 있는 방법이 있나요?

저는 if문으로 해서 처리하려고 하는데 오류가 나네요 ㅠㅠ

--FORMULA에 오는값 추가--

 

by jkson [2017.01.11 15:30:49]

오라클 맞나요?

일단 IF 조건 THEN 형태로 쓰셔야 하구요.

FOR_PAY~ 이 부분이 문자형인 것 같은데 양쪽으로 ' 가 없네요.

ELSE IF -> ELSIF

좀 더 보완하자면

SELECT 절에 FOR_PAY_DEDUCTION. 이 부분도 바인드 변수로 하시고

EMP_CODE 뒷 부분 FOR_PAY_DEDUCTION.EMP_CODE 이 부분도 바인드 변수로 작성해주시면

하드파싱 문제가 없을 겁니다.


by jkson [2017.01.11 15:50:43]

마농님이 다 작성해주셨는데 왜 저를...;;


by 뀽 [2017.01.11 15:52:42]

감사합니다! 오라클 맞아용~ THEN을 안적어서 안됬었네요 ㅠ


by 뀽 [2017.01.11 15:57:28]

아 .. 그리고 일단 THEN을 넣으니까 오류는 안나길래 댓글을 채택했는데 그 뒤에 밑에 마농님 댓글을 봤어요 ㅠㅠ 


by jkson [2017.01.11 15:59:34]

결과가 제대로 안 나올 것 같은데. formula에 어떤 값 오는지 설명을 해주셔야할듯요.


by 뀽 [2017.01.11 16:03:46]

넵 사진으로 추가했고 칼럼이나 변수와의 계산식이 들어가있습니다.


by 마농 [2017.01.11 15:42:10]

1. 굳이 바인드변수 처리 하지 않아도 될 것을 바인드 변수 처리하고 있네요.
  - for_pay_deduction.formular
2. 오히려 바인드 변수 처리해야 할 것을 안하고 있네요.
  - for_pay_deduction.emp_code
 

BEGIN
    IF INSTR(for_pay_deduction.formular, ':') = 0 THEN
        v_column := for_pay_deduction.formular;
    ELSIF INSTR(for_pay_deduction.formular, ':v_over_work_hour') != 0 THEN
        v_column := NVL(v_over_work_hour , 0);
    ELSIF INSTR(for_pay_deduction.formular, ':v_night_work_hour') != 0 THEN
        v_column := NVL(v_night_work_hour, 0);
    END IF;
    v_query := 'SELECT ' || v_column
            || '  FROM employee e  '
            || '     , sal_info si '
            || '     , hobong   h  '
            || ' WHERE e.emp_code      = si.emp_code '
            || '   AND e.emp_code      = :v_emp_code '
            || '   AND e.position_code = h.position_code '
            || '   AND si.hobong       = h.hobong '
               ;
    EXECUTE IMMEDIATE v_query INTO v_price USING for_pay_deduction.emp_code;
END;

 


by 뀽 [2017.01.11 15:55:12]

제가 바인드를 잘몰라서 그런데 ㅠ SQL문 안에 변수를 사용하면 SQL문 안에서 :변수이런식으로 작성하는걸 바인드라고 알고 있는데 ㅠ 잘못알고있는건가요?


by 뀽 [2017.01.11 16:06:47]

그런데 제가 지금 저 소스가 부분소스인데 커서 선언한뒤 LOOP로 돌려서 LOOP문 안에서 저 작업을 수행하고 있는데 EMP_CODE를 바인드 처리해야하나요??


by jkson [2017.01.11 16:12:10]

뀽님 :변수 이런식으로 작성하시는 게 바인드변수가 맞고요. 쿼리를 수행할 때 쿼리의 내용이 한 글자라도 달라지면 오라클 서버는 새로운 쿼리로 인식해서 쿼리를 분석하는 작업을 진행합니다. 해서 바인드 변수를 쓰면 오라클 서버가 '아 이건 저번에 수행했던 거고 이렇게 이렇게 수행하면 빨리 수행되더라' 하는 정보를 가지고 있어서 그 정보를 활용하게 되고 처음 수행할 때보다 빠르게 수행됩니다. 작성하신 것처럼 바인드 변수 없이 작성하시면 매번 쿼리 분석(파싱)을 하게 되어 성능적으로 좋지 않습니다.


by 뀽 [2017.01.11 16:17:22]

아 넵 감사합니다~!!

 


by 우리집아찌 [2017.01.11 15:46:06]

       v_query := ' select empno from test ' ;
       v_query := v_query || ' where  '      ;
               
       if ( v_dept is null ) then
         v_query := v_query || '  emp_no =  '  || v_empno    ;
       else
          v_query := v_query || ' and dept =  '  || v_dept    ;     
       end if;

      DBMS_OUTPUT.PUT_LINE ( 'query:' || v_query );


by jkson [2017.01.11 15:48:59]

마농님 v_column도 문자형일 것 같은데 바인드 변수 처리하는 게 좋지 않나요?


by 마농 [2017.01.11 15:51:28]

for_pay_deduction.formular 에 컬럼명을 받아올거라고 생각했습니다.
컬럼명은 문자열로 연결해줘야지만 정상 동작합니다.


by jkson [2017.01.11 15:52:57]

네 컬럼명일 경우에는 그런데 이 경우에는 :v_over_work_hour 같은 문자형을 받고 있는 것 같아서요. 엉뚱하게 저를 채택하셨네요. 마농님이 다 작성해주셨는데요;


by 마농 [2017.01.11 15:56:18]

컬럼명 또는 변수명을 받아오는 듯 합니다.

컬럼명을 받을 때는 해당 컬럼을 조회하고 변수명을 받을 때는 변수값을 조회하는...


by jkson [2017.01.11 15:58:41]

: 이 없을 경우에 컬럼명을 넣는다는 말씀이시군요~ 요청하신 분이 정확히 알려주셔야할 것 같네요.


by jkson [2017.01.11 16:10:15]

헐~ 마농님 말씀대로 :이 없는 경우에는 컬럼명인가보네요. 손바닥 보듯 다 보이시나봐요. 꾸벅~

아 생각해보니 그냥 값만 받아오면 쿼리로 처리할 필요가 없네요ㅋㅋ 컬럼을 사용하니 쿼리로 작성했겠네요. 경험 부족, 지식 부족이 여실히 드러납니다. 부끄..*-*


by 마농 [2017.01.11 16:11:07]
BEGIN
    v_column := for_pay_deduction.formular;
    v_column := REPLACE(v_column, ':v_over_work_hour' , v_over_work_hour );
    v_column := REPLACE(v_column, ':v_night_work_hour', v_night_work_hour);
    v_query := 'SELECT NVL(' || v_column || ', 0) '
            || '  FROM employee e  '
            || '     , sal_info si '
            || '     , hobong   h  '
            || ' WHERE e.emp_code      = si.emp_code '
            || '   AND e.emp_code      = :v_emp_code '
            || '   AND e.position_code = h.position_code '
            || '   AND si.hobong       = h.hobong '
               ;
    EXECUTE IMMEDIATE v_query INTO v_price USING for_pay_deduction.emp_code;
END;

 


by 뀽 [2017.01.11 16:29:54]

감사합니다! 그런데 :변수를 REPLACE로 바꿔도 여전히 변수로 인식하나요??


by 마농 [2017.01.11 16:32:06]

변수가 아니죠.


by 뀽 [2017.01.11 16:39:33]

변수가 아니면 칼럼인가요??

 


by 마농 [2017.01.11 16:42:44]

문자열입니다. 입력받은 문자열을 조작하는 거죠.

-- 예를 들면
-- 입력값이 다음과 같을 때 ...
    v_over_work_hour := 4;
    for_pay_deduction.formular := '(:v_over_work_hour * h.base_sal * 1.5)';
-- 이 구문을 수행하면 ...
    v_column := for_pay_deduction.formular;
    v_column := REPLACE(v_column, ':v_over_work_hour' , v_over_work_hour );
-- 결과는 ...
    v_column = '(4 * h.base_sal * 1.5)'

 


by 뀽 [2017.01.11 16:46:52]

와~ ㄷㄷ 정말 감사합니당!! 그리고 또 궁금한게 있는데 이 문제랑은 별개로 프로시저에서는 변수에 +=같은 누적이 안먹히는데 이걸 대체할만한 연산자가 있을까요?? 변수:=변수+값 이런식으로 해서 DMBMS_OUPUT으로 변수를 찍어봤는데 이상하게 값이 안찍히더라고요ㅠ


by 마농 [2017.01.11 17:06:42]

+= 연산자는 없구요.
숫자인 경우 + , 문자인 경우 || 사용하세요.
  변수 := 변수 +  값;  -- 숫자 증가.
  변수 := 변수 || 값;  -- 문자 연결.
이렇게 했는데 안찍힌다면? 누적 문제가 아닌 다른 문제입니다.
다른 문제를 찾아보세요.


by 뀽 [2017.01.11 19:39:48]

넵넵 감사합니당 ㅎㅎ

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입