1. BULK COLLECT
... BULK COLLECT INTO collection_name[, collection_name]... |
DECLARE
names name_varray;
mileages number_varray;
BEGIN
SELECT name, mileage
FROM transportation
BULK COLLECT INTO names, mileages
WHERE TYPE = 'AUTOMOBILE'
AND mileage < 20;
-- 컬렉션에서 데이터를 처리한다.
END;
-- 명시적 커서 사용 예제
DECLARE
CURSOR major_polluters IS
SELECT name, mileage
FROM transportation
WHERE TYPE = 'AUTOMOBILE'
AND mileage <20;
names name_varray;
mileages number_varray;
BEGIN
OPEN major_polluters;
FETCH major_polluters BULK COLLECT INTO names, mileages;
-- 컬렉션에서 데이터를 처리한다.
END; |
FETCH ... BULK COLLECT INTO ...[LIMIT rows]; |
DECLARE
CURSOR major_polluters IS
SELECT name
FROM transportation
WHERE TYPE = 'AUTOMOBILE' AND mileage < 20;
names name_varray;
BEGIN
OPEN major_polluters;
FETCH major_polluters
BULK COLLECT INTO names
LIMIT 5000;
...
END; |
DECLARE
-- 컬렉션 유형을 선언
TYPE VehTab IS TABLE OF transportation%ROWTYPE;
-- TYPE으로부터 특정 컬렉션을 예시
gas_guzzlers VehTab;
BEGIN
SELECT *
BULK COLLECT INTO gas_guzzlers
FROM transportation
WHERE mileage < 20;
... 9i 릴리스2 이전에는 오류가 발생하였다.
PLS-00597: expression 'GAS_GUZZLERS' in the INTO list is of wrong type
이전 버전에서는 다중 컬렉션을 선언하고 개별적으로 페치해야 한다.
DECLARE
guzzler_type name_varray;
guzzler_name name_varray;
guzzler_mileage number_varray;
CURSOR low_mileage_cur IS
SELECT vehicle_type, name, mileage
FROM transportation WHERE mileage < 10;
BEGIN
OPEN low_mileage_cur;
FETCH low_mileage_cur BULK COLLECT
INTO guzzler_type, guzzler_name, guzzler_mileage; END; |
CREATE TABLE compensation (
name VARCHAR2(100),
title VARCHAR2(100),
salary NUMBER,
bonus NUMBER,
stock_options INTEGER,
mercedes_benz_allowance NUMBER,
yacht_allowance NUMBER
);
INSERT INTO compensation VALUES (
'John DayAndNight', 'JANITOR', 10000, 500, NULL, NULL, NULL);
INSERT INTO compensation VALUES (
'Holly Cubicle', 'PROGRAMMER', 50000, 2000, NULL, NULL, NULL);
INSERT INTO compensation VALUES (
'Sandra Watchthebucks', 'CFO',
20000000, 2000000, 2000000, 500000, 500000);
INSERT INTO compensation VALUES (
'Hiram Coldheart, XVII', 'CEO',
100000000, 20000000, 20000000, 2500000, 2500000);
CREATE OR REPLACE FUNCTION salforexec (title_in IN VARCHAR2)
RETURN NUMBER
/* Why "for Exec"? Cause the query assumes NOT NULL values
for all of that good stuff you in the SELECT below. */
IS
CURSOR ceo_compensation
IS
SELECT
salary + bonus + stock_options +
mercedes_benz_allowance + yacht_allowance
FROM compensation
WHERE title = title_in;
big_bucks NUMBER;
BEGIN
OPEN ceo_compensation;
FETCH ceo_compensation INTO big_bucks;
RETURN big_bucks;
END;
/
CREATE TYPE name_tab IS TABLE OF VARCHAR2(200);
/
CREATE TYPE number_tab IS TABLE OF NUMBER;
/
DECLARE
big_bucks NUMBER := salforexec ('CEO');
min_sal NUMBER := big_bucks / 50;
names name_tab;
old_salaries number_tab;
new_salaries number_tab;
CURSOR affected_employees (ceosal IN NUMBER)
IS
SELECT name, salary + bonus old_salary
FROM compensation
WHERE title != 'CEO'
AND ((salary + bonus < ceosal / 50) -- underpaid
OR (salary + bonus > ceosal / 10)) -- overpaid and NOT CEO
;
BEGIN
OPEN affected_employees (big_bucks);
FETCH affected_employees BULK COLLECT INTO names, old_salaries;
CLOSE affected_employees;
FORALL indx IN names.FIRST .. names.LAST
-- DECODE문을 이용하여 급여를 조정한다.
UPDATE compensation
SET salary =
DECODE (
GREATEST (min_sal, salary), min_sal, min_sal,
salary / 5)
WHERE name = names (indx)
RETURNING salary BULK COLLECT INTO new_salaries;
FOR indx IN names.FIRST .. names.LAST
LOOP
DBMS_OUTPUT.PUT_LINE (
RPAD (names(indx), 20) ||
RPAD (' Old: ' || old_salaries(indx), 15) ||
' New: ' || new_salaries(indx)
);
END LOOP;
END;
/ |
CURSOR toys_cur IS
SELECT name, manufacturer, preference_level, sell_at_yardsale_flag
FROM my_sons_collection
WHERE hours_used = 0
FOR UPDATE;
CURSOR fall_jobs_cur IS
SELECT task, expected_hours, tools_required, do_it_yourself_flag
FROM winterize
WHERE year = TO_CHAR(SYSDATE, 'YYYY')
FOR UPDATE OF task; |
DECLARE
CURSOR fall_jobs_cur IS
SELECT task, expected_hours, tools_required, do_it_yourself_flag
FROM winterize
WHERE year = TO_CHAR(SYSDATE, 'YYYY');
job_rec fall_jobs_cur%ROWTYPE;
BEGIN
OPEN fall_jobs_cur;
LOOP
FETCH fall_jobs_cur INTO job_rec;
IF fall_jobs_cur%NOTFOUND
THEN
EXIT;
ELSIF job_rec.do_it_yourself_flag = 'YOUCANDOIT'
THEN
UPDATE winterize SET responsible = 'STEVEN'
WHERE CURRENT OF fall_jobs_cur;
COMMIT;
EXIT;
END IF;
END LOOP;
CLOSE fall_jobs_cur; END; |
출처 : http://deviant86.tistory.com/467
-------------------------------------------------------------------------------
------------------------------------ LINE ------------------------------------
-------------------------------------------------------------------------------
SELECTS문에서 한번에 대량의 레코들 취득 하는 경우, BULK COLLECT구를 사용하면
한번에 여러개의 레코드를 취득할수 있으므로 퍼포먼스 향상
Patten 1
-------------------------------------------------------------------------------
DECLARE
TYPE empno_tbl_type IS TABLE OF EMP.EMPNO%TYPE INDEX BY BINARY_INTEGER;
empno_tbl empno_tbl_type;
BEGIN
SELECT EMPNO BULK COLLECT INTO empno_tbl FROM EMP;
IF empno_tbl.COUNT > 0 THEN
FOR i IN empno_tbl.FIRST..empno_tbl.LAST LOOP
UPDATE EMP SET SAL = SAL * 1.05 WHERE EMPNO = empno_tbl( i );
END LOOP;
END IF;
END;
/
Patten 2
-------------------------------------------------------------------------------
DECLARE
TYPE emp_tbl_type IS TABLE OF EMP%ROWTYPE INDEX BY BINARY_INTEGER;
emp_tbl emp_tbl_type;
BEGIN
SELECT * BULK COLLECT INTO emp_tbl FROM EMP;
IF emp_tbl.COUNT > 0 THEN
FOR i IN emp_tbl.FIRST..emp_tbl.LAST LOOP
UPDATE EMP SET SAL = SAL * 1.05 WHERE EMPNO = emp_tbl( i ).EMPNO;
END LOOP;
END IF;
END;
/
Patten 3 커서 이용
-------------------------------------------------------------------------------
DECLARE
CURSOR emp_cur IS
SELECT * FROM EMP;
TYPE emp_tbl_type IS TABLE OF emp_cur%ROWTYPE INDEX BY BINARY_INTEGER;
emp_tbl emp_tbl_type;
BEGIN
OPEN emp_cur;
FETCH emp_cur BULK COLLECT INTO emp_tbl;
CLOSE emp_cur;
IF emp_tbl.COUNT > 0 THEN
FOR i IN emp_tbl.FIRST..emp_tbl.LAST LOOP
UPDATE EMP SET SAL = SAL * 1.05 WHERE EMPNO = emp_tbl( i ).EMPNO;
END LOOP;
END IF;
END;
/
즉,커서를 이용할시 취득할 데이터 수가 많을듯하면 Limit를 사용하여 일정 레코드 단위로
Fetch하는 것이 성능면에서 좋다.
FETCH emp_cur BULK COLLECT INTO emp_tbl LIMIT 100;
출처 : http://avang.tistory.com/65
'SQL' 카테고리의 다른 글
[오라클] rollup과 cube 한방에 이해하기 (0) | 2016.11.24 |
---|---|
ORACLE|KEEP(DENSE_RANK FIRST ORDER BY …) - A컬럼 기준 정렬 후 지정 된 행의 B컬럼값 추출하기 (0) | 2014.08.21 |
DBMS_LOB 관련 함수 (SUBSTR,INSTR,GETLENGTH) (0) | 2013.10.15 |
oracle extract (0) | 2013.10.08 |
oracle XML 저장(extractValue,updateXML,existsNode) (0) | 2013.10.08 |