Procedure 호출 

- Procedure : 쿼리문을 저장하고 필요한 곳에서 실행해야 할 때 사용하는 DBMS 객체

- DBMS에서 언어적인 요소(제어, 연산)를 가져야 할 때

- Oracle DBMS에서는 user_procedures 딕셔너리에서 생성된 Procedure를 확인할 수 있음

- CallableStatement 객체로 Procedure를 호출할 수 있음

- 자바에서 호출 시, SQL의 프로시저가 컴파일 되어있어야 함

 

* Oracle의 Procedure *

- PL/SQL : DBMS에서 언어적인 요소를 구현할 때 사용

- 기본문법(데이터형, 변수, 연산자, 제어문), cursor, function, procedure, trigger, package를 지원

- 컴파일을 한 후 실행함

    > 컴파일 : @파일명.sql

    > 함수 : 간접실행 (쿼리문에 함수를 포함시켜 실행하는 방법)

                   직접실행 (실행기를 사용하여 실행하는 방법 -> execute 또는 exec 사용)

- 작성법) 

    create or replace procedure 프로시저명 (매개변수,,,) 

    is  -- 변수 선언, record 선언(java의 VO같은 거), table 선언(java의 배열 같은 거), cursor 선언

    begin -- 코드 작성(연산, 제어, 쿼리작성 등등)

    end;

    /

- 선언 시 주의)

   > 매개변수 종류 : in parameter (프로시저 외부의 값을 프로시저 내부로 전달하는 일)  //  in은 생략하고 선언 가능

                                   our parameter (프로시저 안에서 처리한 값을 외부로 전달하는 일)

   > 매개변수명은 테이블의 컬럼명과 동일하면 절대 안됨! 식별될 수 있도록 선언 

        ex) sal로 쓰면 sal=sal 항상 참이 될 수 있으므로 in paramter면 in_sal로 선언

- 컴파일) @파일명.sql   -- DOS에서 sqlplus에서 로그인하고 하면 됨

- 실행)

   1) bind 변수 선언 (프로시저 내부의 처리된 값을 SQLPlus에서 저장할 변수)

        > 프로시저 내부의 처리된 값은 out parameter를 타고 나옴

        >  bind 변수는 일시적이라 실행될 때 마다 선언해주어야 함

             var | variable 데이터형 변수명 (크기) -- 크기는 넣어도 되고 안 넣어도 됨

    2) 프로시저를 실행 (직접실행)

        execute | exec 프로시저명 (,,, : 바인드변수명 ,,,) 

        > : in parameter로 들어가는 값 

        > : 바인드면수명 : out parameter로 나오는 값

    3) bind 변수에 저장된 값 출력 (procedure가 처리한 결과값)

        > print 바인드변수명 바인드변수명 바인드변수명 -- 띄어쓰기로 여러 개의 값 줄 수 있음

 

-프로시저 삭제) drop procedure 프로시저명;

 

 

 Java에서의 Procedure 호출 

* CallabeStatement

- procedure를 호출할 때 사용하는 객체

- PreparedStatement Interface의 하위 Interface

- PreparedStatement bind 변수를 사용하여 값을 입력할 수 있음

- SQLPlus의 bind 변수는 CallableStatement의 registerOutparameter로 처리

   > SQLPlus의 bind 변수 : var 변수명 데이터형(크기), procedure에서는 :변수명 으로 사용

 

- 사용법)

1) 쿼리문 생성객체 얻기

    CallabeStatement cstmt = con.prepareCall(프로시저명);

    // 프로시저명에는 이렇게 !  "{ call 프로시저명(?,?,…) }"

2) CallableStatement 바인드 변수에 값 설정

 ① in parameter에 대응되는 bind 변수 (프로시저에 값 할당)

      - cstmt.setXXX (인덱스, 값);

         number -> cstmt.setInt (인덱스, 값), cstmt.setDouble (인덱스, 값);

         varchar2, char -> cstmt.setString(인덱스, 값);

 ② out parameter에 대응되는 bind 변수 (SQLPlus의 bind 변수를 자바 형식으로 선언하는 것)

      - cstmt.registerOutParameter (인덱스, java.sql.Types.상수) ;

      - Oracle에서는 var 변수명 데이터형(크기) 이렇게 했던 걸 위처럼 처리

    * java.sql.Types 클래스 

       - DBMS의 bind변수를 정의할 때 사용하는 데이터형을 java에서 사용할 수 있도록 구현한 클래스 

       - 특정 DBMS에서만 제공하는 데이터형을 지원하지 않음

            > Oracle의 NUMBER 대신 Types.NUMERIC 사용 

            > Oracle의 VARCHAR2 -> Types.VARCHAR

3) 프로시저 실행 

 - CallableStatement는 실행 method가 없으므로, 부모 Interface의 실행 method를 사용함

     > executeQuery(), executeUpdate(), execute() 셋 중에서 실행했다는 의미로 excute()를 사용!

        (어차피 셋다 반환형(rs,int,boolean)이 제대로 나오지 않음)

 * 프로시저를 실행하면 바인드변수(registerOutParameter)에 프로시저가 실행된 결과가 저장됨

4) 실행결과가 저장된 값 받기

- ResultSet 안 씀.

- CallableStatement의 method 사용 : cstmt.getXXX (바인드변수의 인덱스)

 예) registerOutParameter(Types.NUMERIC) 일 때 : cstmt.getInt(인덱스); cstmt.getDouble(인덱스)

        registerOutParameter(Types.VARCHAR) 일 때 : cstmt.getString(인덱스);

 


# 오늘의 코딩 #

- Java에서 Oracle에 생성한 procedure를 사용해보자 

 

# 생성한 프로시저

- in parameter로 name을 받고, out parameter로 msg를 내보냄!

 

# Java에서 호출

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

import javax.swing.JOptionPane;

import test.dao.DbConnection;

/**
 * 이름(varchar2)을 입력하여 (in parameter) 설정된 msg(varcahr2)를 받는 일 (out parameter)
 * @author user
 */
 
public class UseCallableStatement {

	public UseCallableStatement() throws SQLException {

		Connection con = null;
		CallableStatement cstmt = null;

		DbConnection db = DbConnection.getInstance(); // 중복된 일이라 method 만들어 놓음
		
		try {
			// 1.드라이버로딩& 2.커넥션얻기
			con = db.getConn();
			// 3.쿼리문 생성객체 얻기 (프로시저명은 proc_hello)
			cstmt = con.prepareCall("{call proc_hello (?,?)}");
			// 4.바인드 변수 설정
			// in parameter
			cstmt.setString(1, JOptionPane.showInputDialog("이름 입력"));
			// out parameter
			cstmt.registerOutParameter(2, Types.VARCHAR);
			// 5.쿼리수행 후 결과 얻기
			cstmt.execute();
			//프로시저가 실행된 결과는 Out Parameter에 저장됨
			String msg = cstmt.getString(2);
			System.out.println(msg);
			
		} finally {
			// 6.연결 끊기 : CallableStatement는 PreparedStatement의 자식이므로, 종료 method를 부모로 사용 가능
			db.closeDB(null, cstmt, con);
		} // end finally

	}// UseCallableStatement

	public static void main(String[] args) {

		try {
			new UseCallableStatement();
		} catch (SQLException e) {
			e.printStackTrace();
		} // end catch
	}// main

}// class

- name은 다이얼로그를 띄워서 입력받음 (동동)

 

# 출력 결과 #

-> 완료!! ㅎㅎ 

 

 

'Development > JDBC' 카테고리의 다른 글

[JDBC] Cursor 작성 예정  (0) 2021.10.21
[JDBC] ResultSetMetaData / Transaction 처리  (0) 2021.10.19
[JDBC] DAO / PreparedStatement 활용  (0) 2021.10.15
[Java/JDBC] Singleton Pattern  (0) 2021.10.14
[JDBC] SQL Exception / SQL Injection  (0) 2021.10.13

+ Recent posts