개요
바인드 변수는 프로그램에 따라 선언하는 방식이 다릅니다.
•
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
복사