오라클 sql과 pl/sql을 다루는 기술 - 13장.동적 sql
TRANSCRIPT
The Technique of Java Programming
들어가기
이 자료는 교육 등 비영리 목적으로만 사용해야 합니다 !!!!
만든사람 및 책 소개
• 오라클 SQL과 PL/SQL을 다루는 기술 : 오라클 프로그래밍 , 현장 밀착 입문서는 따로 있다 !
• 홍형경
• 주요 저서 : - 〈뇌를 자극하는 오라클 프로그래밍 SQL&PL/SQL
- Head First 시리즈를 비롯해 다수의 책 번역
실행 시점에 생성되어 수행되는 동적 SQL
셋째 마당 . 업무 효율을 높이는 실전 PL/SQL 프로그래밍
13장
01 동적 SQL 이 필요한 이유
NDS
DBMS_SQL
02
실행 시점에 생성되어 수행되는 동적 SQL
03
01
동적 SQL
동적 SQL 이 필요한 이유
● 쿼리문을 문자열 형태로 만들어 실행하는 SQL
쿼리를 실행할 때마다 SQL 문이 변경
● 컴파일 시에 SQL 문장이 확정되지 않는 경우
● PL/SQL 블록 상에서 DDL 문을 실행해야 할 경우
● PL/SQL 블록 상에서 ALTER SYSTEM/SESSION 명령어를 실행해야 할 경우
02
원시 동적 SQL (NDS, Native Dynamic SQL)
NDS
● EXECUTE IMMEDIATE 문을 사용
● 구문
EXECUTE IMMEDIATE SQL 문 _ 문자열 [ INTO OUT 변수 1, OUT 변수 2, …] [ USING [ IN | OUT | IN OUT] 매개변수 1, [ IN | OUT | IN OUT] 매개변수 2, … ;
● SELECT 문 사용 예
EXECUTE IMMEDIATE ' SELECT employee_id, emp_name, job_id FROM employees WHERE job_id = ''AD_ASST'' ';
02
원시 동적 SQL (NDS, Native Dynamic SQL)
NDS
● SELECT 문 사용 예
-- SELECT 결과를 vn_emp_id, vs_emp_name, vs_job_id 변수에 받는다 EXECUTE IMMEDIATE 'SELECT employee_id, emp_name, job_id
FROM employees WHERE job_id = ''AD_ASST'' ' INTO vn_emp_id, vs_emp_name, vs_job_id;
-- SQL 문을 변수에 담은 후 사용 vs_sql := 'SELECT employee_id, emp_name, job_id FROM employees WHERE job_id = ''AD_ASST'' ';
EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id;
02
바인드 변수 처리 1
NDS
● WHERE 절 사용 시 상수가 아닌 변수를 사용
● 쿼리 구문의 WHERE 절에서는 : 변수명 형태로 사용
변수명은 아무 명칭이나 사용 가능하며 데이터 타입이 같다면 중복사용도 가능
● EXECUTE IMMEDIATE 문에서는 USING 다음에 선언한 변수 나열
쿼리구문에서 선언한 변수의 데이터 타입과 순서를 맞춰야 한다
02
바인드 변수 처리 1
NDS
● 사용 예
DECLARE … -- 바인드 변수 선언과 값 설정 vs_job employees.job_id%TYPE := 'SA_REP'; vn_sal employees.salary%TYPE := 7000; vn_manager employees.manager_id%TYPE := 148;BEGIN -- SQL 문을 변수에 담는다 . ( 바인드 변수 앞에 : 를 붙인다 ) vs_sql := 'SELECT employee_id, emp_name, job_id
FROM employees WHERE job_id = :a AND salary < :b AND manager_id = :c ';
-- SQL 문에서 선언한 순서대로 USING 다음에 변수를 넣는다 . EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id USING vs_job, vn_sal, vn_manager; …END;
02
바인드 변수 처리 2
NDS
● 익명블록 , PL/SQL 함수나 프로시저도 동적 SQL 사용 가능
● 일반 SQL 문 실행 때와는 달리 BEGIN ~ END; 를 붙여야 함
vs_sql := 'BEGIN ch13_bind_proc1 (:a, :b, :c); END;'; EXECUTE IMMEDIATE vs_sql USING vs_data1, vn_data2, vd_data3;
● 또한 바인드변수 명도 맞춰야 함 중복 사용 불가
vs_sql := 'BEGIN ch13_bind_proc1 (:a, :b, :c); END;'; (O)
vs_sql := 'BEGIN ch13_bind_proc1 (:a, :a, :c); END;'; (X)
02
바인드 변수 처리 2
NDS
● OUT, IN OUT 매개변수의 경우 USING 절에서 OUT, IN OUT 을 명시해야 함
EXECUTE IMMEDIATE vs_sql USING vs_data1, OUT vs_data2, IN OUT vs_data3;
02
DDL 문 , ALTER SESSION 실행
NDS
● PL/SQL 상에서는 DDL 문 사용 불가하지만 , 동적 SQL 을 이용하면 사용 할 수 있음 vs_sql := 'CREATE TABLE ch13_ddl_tab ( col1 VARCHAR2(30) )' ; EXECUTE IMMEDIATE vs_sql;
● ALTER SESSION 명령어도 동적 SQL 을 이용하면 사용 가능
vs_sql := 'ALTER SESSION SET NLS_DATE_FORMAT = "YYYY/MM/DD"'; EXECUTE IMMEDIATE vs_sql;
02
OPEN FOR 문
NDS
● 단일 로우를 반환하는 SELECT 문의 경우 INTO 절을 이용해 값을 가져올 수 있음
● 다중 로우를 반환하는 SELECT 문의 경우에는 OPEN FOR 문과 커서 사용
● 구문
OPEN 커서변수 FOR 동적 _SQL 문장 USING 바인드변수 1, 바인드변수 2, … ;
● 커서변수에 동적 _SQL 문장의 결과값을 받아 루프를 돌며 반환된 값을 참조
02
BULK COLLECT INTO 절
NDS
● 다중 로우를 반환하는 SELECT 문의 결과를 일반 변수가 아닌 레코드나 컬렉션 변수에 담을 수
있는데 , 이 때 BULK COLLECT INTO 절을 사용해 한 번에 값을 할당함
● 다중 로우를 반환하는 SELECT 문의 경우에는 OPEN FOR 문과 커서 사용
● 사용 예
DECLARE -- 중첩 테이블 변수 선언 vr_physicist NT_physicist; BEGIN -- BULK COLLECT INTO 절 ( 패치가 한 번에 이루어진다 ) SELECT * BULK COLLECT INTO vr_physicist FROM ch13_physicist; … …
03
DBMS_SQL
DBMS_SQL
● 동적쿼리는 NDS 방식과 DBMS_SQL 패키지를 이용해 처리
● NDS 보다 사용법은 복잡하지만 더 많은 기능을 보유
03
DBMS_SQL 처리 순서
DBMS_SQL
● 커서 열기 : OPEN_CURSOR 함수 사용
DBMS_SQL.OPEN_CURSOR ( security_level IN INTEGER ) RETURN INTEGER;
● 파싱 : PARSE 프로시저 사용
DBMS_SQL.PARSE ( c IN INTEGER, statement IN VARCHAR2, language_flag IN INTEGER, edition IN VARCHAR2 DEFAULT NULL, apply_crossedition_trigger IN VARCHAR2 DEFAULT NULL, fire_apply_trigger IN BOOLEAN DEFAULT TRUE);
TYPE varchar2a IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
03
DBMS_SQL 처리 순서
DBMS_SQL
● 바인드 변수 연결 : BIND_VARIABLE 와 BIND_ARRAY 프로시저
DBMS_SQL.BIND_VARIABLE ( c IN INTEGER, name IN VARCHAR2, value IN <datatpe> );
EXECUTE IMMEDIATE 문에서 USING 다음에 기술하는 바인드 변수 역할
SQL 문장에 기술한 바인드 변수 개수만큼 BIND_VARIABLE 프로시저를 호출해야 함
03
DBMS_SQL 처리 순서
DBMS_SQL
● 바인드 변수 연결 : BIND_VARIABLE 와 BIND_ARRAY 프로시저
DBMS_SQL.BIND_ARRAY ( c IN INTEGER, name IN VARCHAR2, <table_variable> IN <datatype> [ ,index1 IN INTEGER, index2 IN INTEGER)] );
바인드 변수 자체를 배열 형태로 만들어 연결
주로 INSERT, UPDATE 문을 처리할 때 사용
03
DBMS_SQL 처리 순서
DBMS_SQL
● 결과 선택 컬럼 정의 : DEFINE_COLUMN 프로시저
ㆍ 컬럼 타입이 문자형이 아닐 경우
DBMS_SQL.DEFINE_COLUMN ( c IN INTEGER, position IN INTEGER, column IN <datatype>);
ㆍ 컬럼 타입이 문자형일 경우
DBMS_SQL.DEFINE_COLUMN ( c IN INTEGER, position IN INTEGER, column IN VARCHAR2 CHARACTER SET ANY_CS, column_size IN INTEGER);
03
DBMS_SQL 처리 순서
DBMS_SQL
● 쿼리 실행 : EXECUTE 함수
DBMS_SQL.EXECUTE ( c IN INTEGER) RETURN INTEGER;
● 결과 패치 : FETCH_ROWS 함수
DBMS_SQL.FETCH_ROWS ( c IN INTEGER) RETURN INTEGER;
03
DBMS_SQL 처리 순서
DBMS_SQL
● 패치된 결과값 받아오기 : COLUMN_VALUE 프로시저
DBMS_SQL.COLUMN_VALUE ( c IN INTEGER, position IN INTEGER, value OUT <datatype> [,column_error OUT NUMBER] [,actual_length OUT INTEGER]);
● 커서 닫기 : CLOSE_CURSOR 프로시저
DBMS_SQL.CLOSE_CURSOR ( c IN OUT INTEGER );
03
DBMS_SQL.TO_REFCURSOR 함수
DBMS_SQL
● 파싱되고 실행된 커서를 약한 커서 타입으로 변환하는 함수
SELECT 한 결과를 커서 변수로 받은 후 NDS 방식으로 처리
● 구문
DBMS_SQL.TO_REFCURSOR( cursor_number IN OUT INTEGER) RETURN SYS_REFCURSOR;
● SELECT 리스트에 선택된 컬럼 개수만큼 DEFINE_COLUMN 프로시저를 호출하고 루프를
돌며 패치하면서 COLUMN_VALUE 프로시저를 호출할 필요 없음
03
DBMS_SQL.TO_CURSOR_NUMBER 함수
DBMS_SQL
● TO_REFCURSOR 함수와는 반대로 커서타입을 숫자형인 커서 번호로 반환
● 구문
DBMS_SQL.TO_CURSOR_NUMBER( rc IN OUT SYS_REFCURSOR) RETURN INTEGER;
03
NDS 와 DBMS_SQL
DBMS_SQL
● NDS : 사용법이 쉽고 코드가 간결
● DBMS_SQL : NDS 에 비해 사용법은 어려우나 훨씬 다양한 기능 수행
● 두 가지 방법 중 상황에 따라 적절한 방식 사용