기술 정보
home
채널 소개
home

바인드 변수 치환 방법(BIND_VARIABLE)

문서 유형
기술 정보
분야
App개발
키워드
BIND_VARIABLE
varchar
date
적용 제품 버전
6F S06

개요

바인드 변수는 프로그램에 따라 선언하는 방식이 다릅니다.
JAVA 프로그램, orange for tibero : '?' 형태로 선언
cli 프로그램, tbsql : ':문자' 형태로 선언
JAVA 프로그램에서 실행된 쿼리의 plan stat 정보 확인을 위해 tbsql에서 쿼리를 실행해야 할 경우, 쿼리 내에 '?' 형태로 바인드 처리한 부분을 ':문자' 형태로 치환하는 작업이 필요합니다.
이 때 아래와 같이 psm을 사용하면 tbsql 에서 실행 가능한 쿼리로 간단히 변경할 수 있습니다.
int col1 = 1; String col2 = "A"; Date col3 = new Date(System.currentTimeMillis()); strSQL = "select col1, col2, col3 from tibero.test where col1 = ? and col2 = ? and to_char(col3, 'yyyy/mm/dd') = ?";
SQL
복사
이 문서에서는 쿼리 내에 바인드 변수가 '?'로 선언되어 있는 경우 tbsql 에서 실행할 수 있는 바인드 변수로 치환하는 방법을 예시와 함께 설명합니다.

방법

적용 가능 조건

BIND_VARIABLE_CAPTURE=Y인 경우
바인드 변수 타입: number, varchar, date인 경우

실행 구문

1.
변경하고자 하는 쿼리의 sql_id, plan_hash_value 값을 조회합니다.
2.
조회된 sql_id, plan_hash_value 값을 아래의 psm 에 입력하고 실행합니다.
set serverout on DECLARE v_cnt number; v_str varchar(4000); v_tmp1 varchar(4000); v_tmp2 varchar(4000); v_tmp3 varchar(4000); v_sqlid varchar(13); v_plan_val number; v_type varchar(128); v_len number; v_val varchar(4000); BEGIN v_cnt := 0; v_str := ''; v_tmp1 := ''; v_tmp2 := ''; v_tmp3 := ''; v_sqlid := ''; v_plan_val := 0; v_type := ''; v_len := 0; v_val := ''; --sql_id, plan_hash_value 값 입력 v_sqlid := '4mvt49cc3tgaw'; v_plan_val := '1519877515'; --동일한 sql_id 와 plan_hash_value 를 가진 sql_text 내용을 v_str 에 병합 FOR l_cnt IN (select sql_text from V$SQLTEXT_WITH_NEWLINES2 where sql_id = v_sqlid and plan_hash_value = v_plan_val order by piece) LOOP v_str := v_str || chr(13)||chr(10) || l_cnt.sql_text; END LOOP; --바인드 갯수 확인 select regexp_count(v_str,'\?') into v_cnt from dual; v_tmp3 := v_str; --바인드변수 선언 --V$SQL_BIND_CAPTURE_ALL 에서 마지막 시점의 바인드 값 확인 FOR l_cnt IN 1..v_cnt LOOP select type_name, length, value into v_type, v_len, v_val from (select type_name, length, value, time_captured as time_captured from V$SQL_BIND_CAPTURE_ALL where sql_id = v_sqlid and plan_hash_value = v_plan_val and position = l_cnt-1 group by sql_hash_value, position, type_name, length, value, time_captured order by time_captured desc) where rownum = 1; IF v_type = 'VARCHAR2' THEN v_tmp1 := 'var a'||l_cnt||' ' || v_type || '(' || v_len || ')' || ';'; v_tmp2 := 'exec :a'||l_cnt||' := ' || '''' || v_val || ''';'; ELSIF v_type = 'DATE' THEN v_tmp1 := 'var a'||l_cnt||' ' || v_type || ';'; v_tmp2 := 'exec :a'||l_cnt||' := ' || '''' || v_val || ''';'; ELSE v_tmp1 := 'var a'||l_cnt||' ' || v_type || ';'; v_tmp2 := 'exec :a'||l_cnt||' := ' || v_val || ';'; END IF; dbms_output.put_line (v_tmp1); dbms_output.put_line (v_tmp2); END LOOP; --쿼리에서 ?를 바인드변수로 치환 FOR l_cnt IN 1..v_cnt LOOP select regexp_replace(v_tmp3,'\?',':a'||l_cnt,1,1) into v_tmp3 from dual; END LOOP; dbms_output.put_line (''); dbms_output.put_line (v_tmp3); EXCEPTION WHEN NO_DATA_FOUND THEN null; END; /
SQL
복사

실행 결과

가장 최근에 입력된 바인드 값으로 설정됩니다. 이때 바인드 변수는 ':a+순차적번호'로 설정됩니다.
var a1 NUMBER; exec :a1 := 1; var a2 VARCHAR2(32); exec :a2 := 'A'; var a3 DATE; exec :a3 := '2017/07/11'; select col1, col2, col3 from tibero.test where col1 = :a1 and col2 = :a2 and to_char(col3, 'yyyy/mm/dd') = :a3 PSM completed.
SQL
복사