더북(TheBook)

이러한 동작 방식 때문에 파이프라인 테이블 함수를 사용하면 결과를 좀더 빨리 볼 수 있다. 위의 예제에서는 1부터 10까지만 값을 출력해서 두 테이블 함수의 차이점을 거의 느낄 수 없지만, 많은 연산을 처리할 때는 그 차이를 실감할 수 있을 것이다.

입력

    -- 일반 테이블 함수(4,000,000회 루프)
    SELECT *
      FROM TABLE( fn_ch14_table1 (4000000));

    -- 파이프라인 테이블 함수(4,000,000회 루프)
    SELECT count(*)
      FROM TABLE( fn_ch14_pipe_table (4000000));

필자의 컴퓨터에서 SQL Developer로 이 두 개의 쿼리를 실행시키면, 5,000개의 행을 추출하기까지 일반 테이블 함수는 1.452초, 파이프라인 함수는 0.051초가 걸렸다. 전자는 반환할 컬렉션에 4백만개의 숫자를 모두 담은 후 결과가 출력된 것이고, 후자는 값이 들어오는 즉시 반환되어 출력되므로 이런 미묘한 시간 차이가 발생한 것이다.

이번에는 다른 형태의 테이블 함수를 만들어 보자. 파이프라인 함수는 루프 중간에 PIPE ROW 문을 써서 컬렉션 타입을 반환하므로 루프 안에서 여러 번 사용하면 데이터 역시 여러 번 반환된다. 어떤 형태로 반환되는지 살펴보자.

입력

    CREATE OR REPLACE FUNCTION fn_ch14_pipe_table2 ( p_cur ch14_empty_pkg.emp_refc_t )
      RETURN ch14_cmplx_nt
      PIPELINED
    IS
      -- 입력 커서에 대한 변수 선언
      v_cur  p_cur%ROWTYPE;

      -- 반환할 컬렉션 변수 선언 (컬렉션 타입이므로 초기화를 한다)
      vnt_return  ch14_cmplx_nt :=  ch14_cmplx_nt();
    BEGIN
      -- 루프를 돌며 입력 매개변수 p_cur를 v_cur로 패치
      LOOP
        FETCH p_cur INTO v_cur;
        EXIT WHEN p_cur%NOTFOUND;

        -- 컬렉션 타입이므로 EXTEND 메소드를 사용해 한 로우씩 신규 삽입
        vnt_return.EXTEND();
        -- 컬렉션 요소인 OBJECT 타입에 대한 초기화
        vnt_return(vnt_return.LAST) := ch14_obj_type1(null, null, null, null);
        -- 컬렉션 변수에 커서 변수의 값 할당
        vnt_return(vnt_return.LAST).varchar_col1 := v_cur.emp_name;
        vnt_return(vnt_return.LAST).varchar_col2 := v_cur.phone_number;
        vnt_return(vnt_return.LAST).num_col      := v_cur.employee_id;
        vnt_return(vnt_return.LAST).date_col     := v_cur.hire_date;
        PIPE ROW ( vnt_return(vnt_return.LAST));          -- 첫 번째 반환

        vnt_return(vnt_return.LAST).varchar_col1 := v_cur.job_id;
        vnt_return(vnt_return.LAST).varchar_col2 := v_cur.email;
        PIPE ROW ( vnt_return(vnt_return.LAST));          -- 두 번째 반환
      END LOOP;
      RETURN;
    END;

결과

    FUNCTION FN_CH14_PIPE_TABLE2이(가) 컴파일되었습니다.
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.