오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

25
The Technique of Java Programming

Transcript of 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

Page 1: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

The Technique of Java Programming

Page 2: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

들어가기

이 자료는 교육 등 비영리 목적으로만 사용해야 합니다 !!!!

Page 3: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

만든사람 및 책 소개

• 오라클 SQL과 PL/SQL을 다루는 기술 : 오라클 프로그래밍 , 현장 밀착 입문서는 따로 있다 !

• 홍형경

• 주요 저서 : - 〈뇌를 자극하는 오라클 프로그래밍 SQL&PL/SQL

- Head First 시리즈를 비롯해 다수의 책 번역

Page 4: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

실행 시점에 생성되어 수행되는 동적 SQL

셋째 마당 . 업무 효율을 높이는 실전 PL/SQL 프로그래밍

13장

Page 5: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

01 동적 SQL 이 필요한 이유

NDS

DBMS_SQL

02

실행 시점에 생성되어 수행되는 동적 SQL

03

Page 6: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

01

동적 SQL

동적 SQL 이 필요한 이유

● 쿼리문을 문자열 형태로 만들어 실행하는 SQL

쿼리를 실행할 때마다 SQL 문이 변경

● 컴파일 시에 SQL 문장이 확정되지 않는 경우

● PL/SQL 블록 상에서 DDL 문을 실행해야 할 경우

● PL/SQL 블록 상에서 ALTER SYSTEM/SESSION 명령어를 실행해야 할 경우

Page 7: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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'' ';

Page 8: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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;

Page 9: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

02

바인드 변수 처리 1

NDS

● WHERE 절 사용 시 상수가 아닌 변수를 사용

● 쿼리 구문의 WHERE 절에서는 : 변수명 형태로 사용

변수명은 아무 명칭이나 사용 가능하며 데이터 타입이 같다면 중복사용도 가능

● EXECUTE IMMEDIATE 문에서는 USING 다음에 선언한 변수 나열

쿼리구문에서 선언한 변수의 데이터 타입과 순서를 맞춰야 한다

Page 10: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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;

Page 11: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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)

Page 12: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

02

바인드 변수 처리 2

NDS

● OUT, IN OUT 매개변수의 경우 USING 절에서 OUT, IN OUT 을 명시해야 함

EXECUTE IMMEDIATE vs_sql USING vs_data1, OUT vs_data2, IN OUT vs_data3;

Page 13: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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;

Page 14: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

02

OPEN FOR 문

NDS

● 단일 로우를 반환하는 SELECT 문의 경우 INTO 절을 이용해 값을 가져올 수 있음

● 다중 로우를 반환하는 SELECT 문의 경우에는 OPEN FOR 문과 커서 사용

● 구문

OPEN 커서변수 FOR 동적 _SQL 문장 USING 바인드변수 1, 바인드변수 2, … ;

● 커서변수에 동적 _SQL 문장의 결과값을 받아 루프를 돌며 반환된 값을 참조

Page 15: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 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; … …

Page 16: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

03

DBMS_SQL

DBMS_SQL

● 동적쿼리는 NDS 방식과 DBMS_SQL 패키지를 이용해 처리

● NDS 보다 사용법은 복잡하지만 더 많은 기능을 보유

Page 17: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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;

Page 18: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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 프로시저를 호출해야 함

Page 19: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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 문을 처리할 때 사용

Page 20: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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);

Page 21: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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;

Page 22: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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 );

Page 23: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

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 프로시저를 호출할 필요 없음

Page 24: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

03

DBMS_SQL.TO_CURSOR_NUMBER 함수

DBMS_SQL

● TO_REFCURSOR 함수와는 반대로 커서타입을 숫자형인 커서 번호로 반환

● 구문

DBMS_SQL.TO_CURSOR_NUMBER( rc IN OUT SYS_REFCURSOR) RETURN INTEGER;

Page 25: 오라클 SQL과 PL/SQL을 다루는 기술 - 13장.동적 SQL

03

NDS 와 DBMS_SQL

DBMS_SQL

● NDS : 사용법이 쉽고 코드가 간결

● DBMS_SQL : NDS 에 비해 사용법은 어려우나 훨씬 다양한 기능 수행

● 두 가지 방법 중 상황에 따라 적절한 방식 사용