(이 모든 오라클 10g입니다) :비 벌크 바인딩 PL/SQL 코드를 벌크 바인딩 코드로 변환해야하는 이유는 무엇입니까? 그리고 Buk 바인딩을 지켜야 할 이유가 있습니까?
내가 대학에서 나의 첫 직장에있어CREATE OR REPLACE FUNCTION bar(...)
IS
v_first_type VARCHAR2(100) ;
v_second_type VARCHAR2(100);
CURSOR cur IS SELECT a,b FROM source_table ;
v_a int;
v_b char;
BEGIN
OPEN cur;
<<l_next>> --10G doesn't have the continue statement.
LOOP
FETCH cur INTO v_a, v_b ;
EXIT WHEN cur%NOTFOUND ;
--Ignore Record Case: ignore the record entirely
IF a == -1 THEN
-- do something
GOTO l_next ; --10g doesn't have the continue statement.
ELSE
-- do something else
v_first := 'SUCCESS' ;
END IF;
-- Transform Case:
IF b == 'z' THEN
-- do something
v_second := 'something';
ELSE
-- do something
v_second := 'something else';
END IF;
INSERT INTO report_table VALUES (v_first, v_second);
END LOOP;
CLOSE cur;
EXCEPTION
...
END;
. 위의 일반적인 프레임 워크처럼 보이는 몇 가지 레거시 코드를 살펴 보았습니다. (몇 줄의 코드가 길고 훨씬 복잡한 처리 (세트 기반 솔루션이 가능하지 않음)를 제외하고는).
하나의 테이블에서 커서로 많은 행을 가져 와서 커서를 반복하고, 변환을 수행하고, 결과를 보고서 테이블에 삽입합니다. 커서는 모든 레코드를 삽입하지 않습니다 - 레코드에 문제가 있거나 어떤 이유로 든 그것을 좋아하지 않으면 레코드를 삽입하지 않고 건너 뜁니다 (GOTO 문 참조).
문제 1 : 끝에 FORALL을 수행하는 대신 루프 내부에서 삽입이 하나씩 발생합니다.
문제 2 : 커서는 BULK COLLECT를 사용하지 않습니다.
또한 BULK COLLECT를 다시 사용하지 않는 커서가있는 저장 프로 시저가 있으며 커서의 레코드를 반복하면서이 함수를 실행합니다. 반복되는 각 레코드의 끝에 하나의 커밋이 발행됩니다. 여기에 내가 쓴 함수에는 커밋이 없다. 결합 배열로 COLLECT BULK 사용)
CREATE OR REPLACE FUNCTION bar(...)
IS
CURSOR cur IS SELECT a,b FROM source_table ;
TYPE t_source IS TABLE OF cur%ROWTYPE INDEX BY PLS_INTEGER;
TYPE t_report IS TABLE OF destination_table%ROWTYPE INDEX BY PLS_INTEGER;
v_sources t_source;
v_reports t_report
v_report_inx INT := 0; -- To Prevent Sparse Collection
BEGIN
OPEN cur;
<<l_next>> --10G doesn't have the continue statement.
LOOP
FETCH cur BULK COLLECT INTO v_sources LIMIT 100 ;
EXIT WHEN v_sources.count = 0 ;
FOR i IN 1 .. v_sources LOOP
--Ignore Record Case: ignore the record entirely
IF v_sources(i).a == -1 THEN
-- do something
GOTO l_next ; --10g doesn't have the continue statement.
ELSE
-- do something else
v_reports(v_report_inx).first := 'SUCCESS' ;
END IF;
-- Transform Case:
IF v_sources(i).b == 'z' THEN
-- do something
v_reports(v_report_inx).second := 'something';
ELSE
-- do something
v_reports(v_report_inx).second := 'something else';
END IF;
v_report_inx := v_report_inx + 1;
END LOOP;
END LOOP;
FORALL i in 1 .. v_reports.count
INSERT INTO report_table (first, second) VALUES (v_reports(i).first, v_reports(i).v_second);
CLOSE cur;
EXCEPTION
...
END;
재질 변화가 1이고, 2)의 다른 연결 배열 중 FORALL 사용 :
는 I는 다음과 같이 표시하는 코드를 재기록 할.
나는 두 가지 질문이 있습니다
내가 처음 코드에서 제공하는 프레임 워크를 기반으로1) 내 변경이 그것을 할 수있는 가장 뛰어난 방법입니다? 다른 방법으로 해 주시겠습니까?
2) 누군가가 대량 수거 및 포틀링을 사용하지 않을 것이라고 생각하지 않는 이유가 있습니까? 아마도 레거시 코드에서 아직 실현하지 못했던 복잡한 처리가 있을까요? 이 코드는 원래 2002 년에 만들어 졌으므로 (그래서 나는 8i 또는 9i라고 가정 할 것입니다) 그 이후로 업데이트되었습니다. 9i had bulk binding. 8i also은 벌크 바인딩을 가졌다. 두 가지 모두 연관 배열을 가졌습니다. 그래서 저는 그들이 대량 바인딩을 사용하지 않았던 이유가 있어야만합니다.
11g에서 Oracle PL/SQL optimizer는 자신의 코드를 대량으로 사용하도록 "변환"합니다. 때로는 차이점을 측정 할 수없는 경우가 있습니다. – ibre5041
처리가 간단한 경우 가장 좋은 방법은 SQL 문으로 변환하는 것입니다. 파이프 라인 기능을 살펴보십시오. 오라클 문서의 데이터웨어 하우스 책에는 대량 etl 프로세스를 구현하는 방법에 대한 많은 아이디어가 있습니다. – haki
@ivan, 그건 멋지다. 나는 몰랐다. 그러나 우리는 직장에서 10g을 사용합니다. 이 기능은 현재 존재하지 않습니까? 그 소식통을 올리시겠습니까? 나는 그것을 읽고 싶다. –