DataBase/Oracle
CURSOR (커서)
H_Develop
2022. 6. 13. 19:26
SQL 문장을 처리한 결과를 담고 있는 메모리 영역을 가리키는 일종의 포인터.
Row는 여러개인데, 커서를 사용하면 Row에 순차적으로 접근이 가능하다.
묵시적 커서 : SQL문장이 실행될 때마다 자동으로 만들어져 실행되는 커서
4가지 속성을 제공
▪ SQL%ROWCOUNT : 최근 실행된 쿼리의 행의 개수 반환
▪ SQL%FOUND : 최근에 실행된 SQL문의 결과 행 존재 유무, 결과 값이 있을 때 TRUE를 리턴
▪ SQL%NOTFOUND : SQL%FOUND와 반대
▪ SQL%ISOPEN : 최근에 실행된 SQL문의 묵시적 커서의 종료 유무.
커서의 속성
▪ %ISOPEN : TRUE, FALSE
▪ %FOUND : NULL, TRUE, FALSE, INVALID_CURSOR
▪ %NOTFOUND : NULL, FALSE, TRUE, INVALID_CURSOR
▪ %ROWCOUNT : INVLID_CURSOR 등이 있다.
명시적 커서 : 사용자가 직접 정의해서 사용하는 커서
CURSOR(커서 선언).
OPEN(커서 열기),
FETCH ~ INTO(커서가 가리키고 있는 곳에 값 넣기),
CLOSE(커서 닫기)의 4 단계로 진행된다.
커서의 구조는
‘cursor 커서_명 (매개변수1, 매개변수2, ...)
is
select 문’
OE 사용자
DECLARE // 커서 선언
product_id varchar2(100); // 한줄한줄 세미클론 찍어줘야 함.
product_name varchar2(100);
CURSOR ex_cur // ex_cur 생성
IS
SELECT product_id, product_name FROM products; // products table의 id 와 name을 넣는다.
BEGIN
OPEN ex_cur;
DBMS_OUTPUT.PUT_LINE('제품 코드 제품 명');
LOOP
FETCH ex_cur INTO product_id, product_name; // product_id, product_name 내용을 가져온다.
EXIT WHEN ex_cur $NOTFOUND // 더이상 db가 없을 때, 종료
DBMS_OUTPUT.PUT_LINE(product_id || ' ' || product_name); // 출력화면
END LOOP;
CLOSE ex_cur;
END;
// 위에 안됨
set serveroutput on; // 화면에 출력되게 해준다는 뜻.
// 위에 실행해주고 아래 선언해줘야함.
DECLARE ## 커서 선언
PRODUCT_ID varchar2(100);
PRODUCT_NAME varchar2(100);
CURSOR EX_CUR ## 커서_명
IS
SELECT PRODUCT_ID, PRODUCT_NAME FROM PRODUCTS;
BEGIN
OPEN EX_CUR; ## 명시적 커서 오픈
DBMS_OUTPUT.PUT_LINE('제품코드 제품명'); ## 내용 출력
LOOP
FETCH EX_CUR INTO PRODUCT_ID, PRODUCT_NAME; # 커서에서 데이터를 가져와서 넣기
EXIT WHEN EX_CUR %NOTFOUND; # 커서에 더 이상의 데이터가 없을 경우 종료
DBMS_OUTPUT.PUT_LINE(PRODUCT_ID ||' '|| PRODUCT_NAME);
END LOOP;
CLOSE EX_CUR; # 커서 닫기
END;
desc customerss
이름 널? 유형
ID NUMBER(10)
NAME VARCHAR2(20)
AGE NUMBER(10)
ADDRESS VARCHAR2(30)
SALARY NUMBER(10)
select * from customerss
ID NAME AGE ADDRESS SALARY
1 Lee 32 Seoul 2000
2 Park 25 Pusan 1500
3 Kim 23 Incheon 6500
4 Pyo 30 Suwon 82000
5 Hong 22 Daegu 4500
// table 구조와 contants 확인
set serveroutput on
SP2-0863: iSQL*Plus 프로세싱이 완료되었습니다.
DECLARE
total_rows number(2);
BEGIN
UPDATE customerss
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line('no customer selected');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' customer selected ');
END IF;
END;
/
// 모든 직원에 500불의 보너스를 주겠다.
// declare 문에서 같다는 뜻은, ':='
// salary에 모두 500불 추가 되어있다.
set serveroutput on
SP2-0863: iSQL*Plus 프로세싱이 완료되었습니다.
DECLARE
c_id customerss.id%type;
c_name customerss.name%type;
c_addr customerss.address%type;
CURSOR c_customerss is
SELECT id, name, address FROM customerss;
BEGIN
OPEN c_customerss;
LOOP
FETCH c_customerss into c_id, c_name, c_addr;
EXIT WHEN c_customerss%notfound;
dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
END LOOP;
CLOSE c_customerss;
END;
/
// 결과
1 Lee Seoul
2 Park Pusan
3 Kim Incheon
4 Pyo Suwon
5 Hong Daegu
PL/SQL 처리가 정상적으로 완료되었습니다.
변수 사용
set serveroutput on;
create or replace procedure info_hiredd(p_year in CHAR := 0) // CHAR가 변수 타입 0으로 초기화
is
l_emp employees%ROWTYPE; // 변수 하나만 생성해도 원하는 테이블 전체의 컬럼을 선택
cursor emp_cur is
select employee_id, last_name, salary from employees
where to_char(hire_date, 'yyyy') = p_year;
begin
open emp_cur;
fetch emp_cur into l_emp.employee_id, l_emp.last_name, l_emp.salary;
dbms_output.put_line(l_emp.employee_id || ' ' || l_emp.last_name || ' ' || l_emp.salary);
close emp_cur;
end info_hiredd;
/
/*
l_emp 는 table
is l_emp employees%ROWTYPE; // 각 항목 타입을 자동으로 맞추어 l_emp 테이블 생성
rowtype 넣는게
c_id customerss.id%type;
c_name customerss.name%type;
c_addr customerss.address%type; 와는 다르게
employees 의 모든 column 을 가져오는 것
*/
exec info_hiredd('1996');
// 뭐 나와야한다는데 안나옴