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');
// 뭐 나와야한다는데 안나옴