반복문
1. FOR LOOP : 루프를 실행할 데이터의 갯수가 정해져 있을 때
for(int i = 0 ; i < list.size(); i++ )
2. LOOP
3. WHILE : 루프 실행 횟수를 모를때, 루프 실행 조건이 로직에 의해 바뀔 때
FOR LOOP
FOR 인덱스변수 (개발자가 이름부여) IN [REVERSE] 시작인덱스.. 종료인덱스 LOOP
반복실행할 문장;
END LOOP ;
1-5 까지 출력
SET SERVEROUTPUT ON ;
DECLARE
BEGIN
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
END;
/
2~5단까지 구구단 연산
(포맷 신경쓰지 말고)
DECLARE
BEGIN
FOR i IN 2..5 LOOP
DBMS_OUTPUT.PUT_LINE(i)
FOR j IN 1..9 LOOP
DBMS_OUTPUT.PUT_LINE(i*j);
END LOOP;
END;
/
DECLARE
BEGIN
FOR i IN 2..5 LOOP
FOR j IN 1..9 LOOP
DBMS_OUTPUT.PUT_LINE( i ||'*'|| j|| '=' || i*j );
END LOOP;
END LOOP;
END;
/
WHILE
java
while (조건식) {
{
while 조건식 LOOP
반복할 문장;
END LOOP ;
DECLARE
i NUMBER := 1;
BEGIN
WHILE i < 5 LOOP
DBMS_OUTPUT.PUT_LINE(i);
i := i + 1;
END LOOP;
END;
/
**커서 : 패치를 직접하는것
변수가 필요가 없다 (V_SAL) 같은 . 한건,두건 패치하는것.
변수가 엄청많은 컬럼의 데이터값이면 이것을 변수에 저장하려면 우선 --에 올려야하는데 그게 메모리가 부족할 수 있어서 패치를 쓰는것.
참고사항
NETWORK 에서 전달된다.
# (사용자가 읽는것) @500 ( 전체데이터)
&10 (사이즈)
네트워크 작업은 한번 & 에서 # 로 갈때 임시저장하는곳& 크기가 작아서 ( 총 @개를 다 해야하면) 여러번 가야하면 네트워크 부하가 걸린다.
적당한 사이즈를 유지해야한다.
&이 작으면 : 응답이빠른것 대신 500을 다옮기는데 총 시간은 느려짐
&이 크면 응답은 느리지만 500 전체시간은 빨라진다.
--REVERSE 1 -> 10 을 10 -> 1로 돌 때
SQL CURSOR : SELECT 문에 의해 추출된 데이터를 가리키는 포인터
SELECT 문 처리 순서
1. 실행계획 생성 OR 기 생성된 계획 찾기
2. 바인드 변수 처리
3. 실행
4. ******* 인출
커서를 통해 개발자가 인출 하는 과정을 통제함으로써 테이블 타입변수에 SELECT 결과를 모두 담지 않고도 ( 메모리 낭비 없이 )
효율적으로 처리하는 것이 가능하다.
커서의 종류
1. 묵시적 커서 - 커서 선언없이 실행한 SQL에 대해서 오라클 서버가 스스로 생성, 삭제하는커서
2. 명시적 커서 - 개발자가 선언하여 사용하는 커서
커서의 속성
커서명%ROWCOUNT : 커서에 담긴 행의 갯수
커서명%FOUND : 커서에 읽을 행이 더 있는지 여부
커서명%NOTFOUND : 커서에 읽을 행이 더 없는지여부
커서명%ISOPEN : 커서가 메모리에 선언되어 사용 가능한 상태 여부
커서 사용법
1. 커서 선언
CURSOR 커서이름 IS
SELECT 쿼리
2. 커서 열기
OPEN 커서이름;
3. 커서로부터 패치
FETCH 커서이름 INTO 변수 ;
4. 커서 닫기
CLOSE 커서이름;
DEPT 테이블의 부서번호deptno, 부서이름dname을 CURSOR 를 통해 데이터 출력
DECLARE
/**/
CURSOR c_dept IS
SELECT deptno, dname
FROM dept ;
v_deptno dept.deptno%TYPE;
v_dname dept.dname%TYPE;
BEGIN
/* 2. 커서열기 */
OPEN c_dept;
/*3. 데이터 패치*/
lOOP
FETCH c_dept INTO v_deptno , v_dname;
EXIT WHEN c_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('v_deptno : ' || v_deptno || ' , v_dname : ' || v_dname);
END lOOP;
CLOSE c_dept;
END;
/
명시적 커서 FOR LOOP : FOR LOOP 와 명시적 커서를 결합한 형태로 커서 OPEN , FETCH, CLOSE 단계를 FOR LOOP 에서 처리하여
개발자가 사용하기 쉬운형태로 제공
사용방법 ( JAVA 향상된 FOR 문과 비슷 )
FOR (String name : names )
사용방법
FOR 레코드이름 IN 커서 LOOP
반복할 문장;
END LOOP
DECLARE
CURSOR c_dept IS
SELECT deptno, dname
FROM dept ;
v_deptno dept.deptno%TYPE;
v_dname dept.dname%TYPE;
BEGIN
FOR rec IN c_dept LOOP
DBMS_OUTPUT.PUT_LINE('rec.deptno : ' || rec.deptno || ' , rec.dname : ' || rec.dname);
END LOOP;
END;
/
파라미터가 있는 커서 : 함수처럼 커서에 인자를 전달해서 실행시 조건을 추가할 수 있다.
커서선언시 인자 명시
CURSOR 커서이름 ( 파라미터명 파라미터타입 ) IS
SELECT *
FROM emp
WHERE deptno = 파라미터명;
emp 테이블의 특정 부서에 속하는 사원들을 조회할 수 있는 커서를 커서 파라미터를 통해 생성 (사원이름, 사원번호 )
DECLARE
CURSOR c_emp ( P_deptno emp.deptno%TYPE) IS
SELECT empno, ename
FROM emp
WHERE deptno = p_deptno;
BEGIN
FOR rec IN c_emp(10) LOOP
DBMS_OUTPUT.PUT_LINE('rec.empno : ' || rec.empno || ' , rec.ename : ' || rec.ename ) ;
END LOOP ;
END;
/
쿼리가 짧을 경우 FOR LOOP 에 커서를 인라인 형태로 작성하여 사용가능
==> DECLARE 절에 커서를 선언하지 않음
FOR 레코드명 in (SELECT 쿼리) LOOP
END LOOP;
DECLARE
BEGIN
FOR rec IN (SELECT deptno , dname FROM dept) LOOP
DBMS_OUTPUT.PUT_LINE('rec.deptno : ' || rec.deptno || ' , rec.dname : ' || rec.dname);
END LOOP;
END;
/
SELECT (SYSDATE + 5) - SYSDATE
FROM dual;
코드
DECLARE
v_date dt.dt%TYPE;
nexdate dt.dt%TYPE;
result NUMBER := 0 ;
minus dt.dt%TYPE;
BEGIN
SELECT dt INTO v_date
FROM dt
WHERE dt = TO_DATE('20201017' , 'YYYYMMDD' )
SELECT dt into nexdate
FROM
WHERE dt = TO_DATE('20201017' , 'YYYYMMDD' )
minus := v_date - nextdate ;
result := result + minus ;
i := i+1;
END LOOP ;
DBMS_OUTPUT.PUT_LINE("result");
END;
/
DECLARE
i NUMBER := 1;
v_date dt.dt%TYPE;
nexdate dt.dt%TYPE;
result NUMBER := 0 ;
minus dt.dt%TYPE;
BEGIN
WHILE i <= 8 LOOP
SELECT dt INTO v_date
FROM
(SELECT ROWNUM RN, DT
FROM dt) A
WHERE rn = i ;
SELECT dt into nexdate
FROM
(SELECT ROWNUM RN, DT
FROM dt ) A
WHERE rn = i+1;
minus := v_date - nextdate ;
result := result + minus ;
i := i+1;
END LOOP ;
DBMS_OUTPUT.PUT_LINE("result");
END;
/
---답
CREATE OR REPLACE PROCEDURE avgdt IS
TYPE t_dt IS TABLE OF dt%ROWTYPE INDEX BY BINARY_INTEGER;
v_dt t_dt;
diff_sum NUMBER := 0 ;
BEGIN
SELECT dt BULK COLLECT INTO v_dt
FROM dt
ORDER BY dt DESC;
FOR i IN 1..v_dt.COUNT-1 LOOP
diff_sum := diff_sum + v_dt(i).dt - v_dt(i+1).dt;
END LOOP ;
DBMS_OUTPUT.PUT_LINE( diff_sum / (v_dt.COUNT-1));
END;
/
EXEC avgdt;
실습 pro3 을 dt 테이블로 sql에서 사용해보기
SELECT AVG(min)
FROM
( SELECT dt , lead (dt ) OVER (order by dt ) newdt , lead (dt ) OVER (order by dt ) - dt min
FROM dt)
//분석함수의 결과값이 일반 그룹함수의 인자로 사용할 수 없다.
SELECT AVG(min)
FROM
( SELECT dt - lead (dt ) OVER (order by dt desc ) min
FROM dt)
좀더 집합적인부분이다.
SELECT (MAX(dt) - MIN( dt))/ (COUNT(*) -1 )
FROM dt;
댓글
댓글 쓰기