오라클 함수의 필요한 필드 파라미터로 전달해 조회하는방법 문의입니다. 0 6 1,835

by 오석영 [PL/SQL] [2017.04.11 09:11:37]


create or replace function get_member_cmcode( p_cate varchar2, p_code varchar2, p_retfield varchar2)
return varchar2 as
  l_str varchar2(1000);
  nstr varchar2(30);
begin
  l_str:='';
  for emp_cur in (select * from cm_code where cate=p_cate and code=p_code) loop
  --  l_str := l_str||'-'||emp_cur.codenm;

  -->

      l_str := l_str||'-'||emp_cur.[p_retfield];    <- 커서필드를 파라미터로 넘기는 방법을 못찾았습니다.
  end loop;

  if (substr(l_str,1,1)='-') then
    l_str := substr(l_str,2,length(l_str)-1);
  end if;
  return l_str;

end;
/

 

이 함수에서 세번째 파라미터로 "codenm" 이라는 필드를 조회할 경우 "emp_cur.[p_retfield]" 는 안되더군요.

임의의 필드명을 이 함수로 전달해서 조회하는 방법이 없을까요?

하다못해 조회 레코드(커서)의 몇번째 필드값(select code, codenm from cm_code 일때 두번째인 codenm을 리턴가능해도 상관없습니다)

by jkson [2017.04.11 09:51:54]

function 내용이 문자열 합치는 함수네요. listagg등의 오라클 함수로 사용하시는 게 나을 듯하네요.

http://www.gurubee.net/article/55512

select listagg(필드명,'-') within group(order by 정렬기준컬럼) from cm_code where cate=p_cate and code=p_code

사용자 함수를 하셔야만 하는 이유가 있나요?

만약 그렇다면 커서문을 동적으로 변동되게 구현하셔야할 것 같구요.

CREATE OR REPLACE FUNCTION GET_MEMBER_CMCODE(P_CATE VARCHAR2, P_CODE VARCHAR2, P_RETFIELD VARCHAR2)
 RETURN VARCHAR2
AS
 L_STR VARCHAR2(1000);
 TYPE CUR IS REF CURSOR;
 V_SQL VARCHAR2(4000);
 V_TEMP VARCHAR2(100);
 C1   CUR;
BEGIN
 L_STR       := '';
 V_SQL       := 'select to_char(' || P_RETFIELD || ') from cm_code a where cate=:p_cate and code =:p_code';

 OPEN C1 FOR V_SQL USING P_CATE, P_CODE;

 LOOP
  FETCH C1 INTO V_TEMP;
  EXIT WHEN C1%NOTFOUND;

  IF L_STR IS NULL THEN
   L_STR       := V_TEMP;
  ELSE
   L_STR       := L_STR || '-' || V_TEMP;
  END IF;
 END LOOP;

 CLOSE C1;

 RETURN L_STR;
END;

 


by 마농 [2017.04.11 09:56:00]

CLOSE ~


by jkson [2017.04.11 09:56:54]

넵 적고 보니 빠져서 바로 수정했습니다^^;


by 오석영 [2017.04.11 09:57:39]

예, 함수에 해당 리턴필드가 일정하지 않아서요.

필요한 필드값은 def1 이라는 필드가 있는데, 어떤 레코드는 "codenm" 이라는 필드이고(해당 레코드의 def1에 "codenm" 저장), 또 어떤 레코드는 "abc1" 필드이고(해당레코드의 def에 "abc1" 저장), 이렇게 필요한 필드가 가변적이다보니 리턴되는 필드가 레코드마다 "def1" 에서 가리키는 필드에 따라 다 달라야해서요.

리턴값은 항상 1개인데, for문을 쓴건 참조한 필드에서 for문을 쓴것을 참조했는데 시간이 없다보니 for문을 제거하지 못한겁니다.

항상 한개이니(pk 필드가 저 파라미터 2개입니다), 문자열을 묶을 가능성은 전혀 없고 한개 레코드를 참조하고 끝납니다.

 

올려주신 방법으로 하니 잘 되네요.

역시 고수이십니다.

정말 감사합니다.

즐거운 하루 되세요.


by 마농 [2017.04.11 10:08:05]

여러건이 아닌 단건이라면?
EXECUTE IMMEDIATE 을 이용하면 됩니다.

CREATE OR REPLACE FUNCTION get_member_cmcode
(p_cate VARCHAR2, p_code VARCHAR2, p_retfield VARCHAR2)
RETURN VARCHAR2
IS
    l_str VARCHAR2(100);
    v_sql VARCHAR2(100);
BEGIN
    v_sql := 'SELECT ' || p_retfield || ' FROM cm_code WHERE cate = :p_cate AND code = :p_code';
    EXECUTE IMMEDIATE v_sql INTO l_str USING p_cate, p_code;
    RETURN l_str;
END;
/

 


by 오석영 [2017.04.11 11:49:19]

예, 답변감사합니다.

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