본문 바로가기

programming/Gukbi

국비 교육 40일차 - View, Subquery

728x90
반응형

오전에는 view를 배우고 오후에는 subquery를 배웠다. 

어제 저녁에 늦게 자서 그런가 오전에 너무 피곤해서 view 부분 수업할때 집중을 제대로 못한거 같다. 

 

지금이라도 복습을 빡세게 해야겠다.. 

-- 2021-02-22 VIEW 
/*
    View : 보여만 주는 문장 (SELECT만 사용이 가능) => DML(INSERT,UPDATE,DELETE)
    => 참조하는 테이블에 영향 
    => DML이 가능한 조건 (DEFAULT => WITH CHECK OPTION) 
    => 읽기 전용 (설정 => WITH READ ONLY)
    정의 : 한개이상의 테이블의 데이터를 참조해서 가상으로 필요한 데이터만 모아서 처리 
    1. View를 사용하는 목적 
       1) 복합한 SQL을 단순화 시킬 수 있다 
       2) 가상 테이블 => 보안 
       3) 주의사항 : 원본 테이블에 영향을 미친다 
    2. View의 종류 
       1) 단순뷰 : 한개의 테이블 참조 => 필요한 데이터만 모아서 관리  
          생성방법 
             CREATE [OR REPLACE] VIEW view_name
             AS
               SELECT * FROM emp;
               => INSERT , UPDATE , DELETE : emp테이블에 영향을 미친다
               
             CREATE [OR REPLACE] VIEW view_name
             AS
              SELECT * FROM emp WITH CHECK OPTION; (DML이 가능 => DEFAULT)
            
            CREATE [OR REPLACE] VIEW view_name
             AS
              SELECT * FROM emp WITH READ ONLY;  (읽기 전용 : SELECT)
       2) 복합뷰 : 한개이상 (JOIN,SUBQuery) 테이블 참조 
           CREATE [OR REPLACE] 
           ======     =======
            생성        수정
           
           CREATE [OR REPLACE] VIEW view_name
           AS
            SELECT empno,ename,hiredate,sal,dname,loc
            FROM emp,dept
            WHERE emp.deptno=dept.deptno; => DML(X)
            
       SQL을 단순화(Java에서 SQL문장을 만드는 경우)
       ===========
         String sql="SELECT empno,ename,hiredate,sal,dname,loc "
                    +"FROM emp,dept "
                    +"WHERE emp.deptno=dept.deptno";
         String sql="SELECT * FROM view_name";
       ***3) 인라인 뷰 : 테이블 대신 SELECT 문장을 이용해서 주로 처리 (페이징기법)
          CREATE [OR REPLACE] (X)
          SELECT * (설정된 컬럼을 벗어날 수 없다
          FROM (SELECT ~) => 보안
                ======== 설정한 컬럼
            
              => SubQuery => 반드시 (subquery) :()안 문장 먼저 실행=> 다른 SQL문장을 실행
          예) SELECT empno,ename,job,hiredate,sal    ==> 오류 
              FROM (SELECT empno,ename,job,sal,comm,deptno => hiredate가 존재하지 않았다
                    FROM emp);
              => FROM (SELECT~)
                      ========= 반드시 ()를 사용한다 
       4) MATERIALIZED VIew (MView) : 구체화된 뷰 (속도가 빠르다 , 11g에서 (XE) => Rewrite가 안된다)
          REWRITE : INSERT , UPDATE , DELETE (12C => XE버전(11g => 18C)
          => SQL문장을 실행하기전에 데이터를 미리 가지고 와서 => 활용 
*/
-- 단순뷰 : 한개의 테이블을 참조해서 가상으로 데이터를 처리 
/*CREATE OR REPLACE VIEW movie_view
AS
 SELECT * FROM movie
 WHERE genre LIKE '%액션%';

SELECT * FROM movie_view;
*/
-- 테이블 생성 
CREATE TABLE dept_test
AS
 SELECT * FROM dept;

SELECT * FROM dept_test;

-- VIEW로  변경
CREATE OR REPLACE VIEW dept_view
AS
  SELECT * FROM dept_test;

SELECT * FROM dept_view;

-- DML
INSERT INTO dept_view VALUES(50,'개발부','서울');
COMMIT;

-- VIEW확인
SELECT * FROM dept_view;
-- 테이블 확인
SELECT * FROM dept_test;

-- DML를 사용하지 않게 만드는 OPTION => WITH READ ONLY
CREATE OR REPLACE VIEW dept_view
AS
  SELECT * FROM dept_test WITH READ ONLY;
  
INSERT INTO dept_view VALUES(50,'개발부','서울');
COMMIT;

-- 복합뷰 : 두개 이상의 테이블을 참조하는 VIEW (집합연산자(UNION,UNION ALL,MINUS,INTERSECT),MERGE,JOIN)
CREATE OR REPLACE VIEW emp_dept_view
AS
  SELECT empno,ename,job,hiredate,sal,dname,loc,grade
  FROM emp,dept,salgrade
  WHERE emp.deptno=dept.deptno
  AND sal BETWEEN losal AND hisal;

SELECT * FROM emp_dept_view; -- SQL문장이 단순화

CREATE OR REPLACE VIEW emp_union
AS
  SELECT * FROM emp_10
  UNION
  SELECT * FROM emp_20;

SELECT * FROM emp_union;

--  인라인뷰 
/*
     View는 필요시에 생성해 놓고 재사용이 가능 (필요한 위치에서 재사용)
     인라인뷰는 생성하는 것이 아니라 FROM에서 SELECT를 이용해서 사용 (서브쿼리 , 인라인뷰 => 페이지 나누기)
     
     형식)
         SELECT * 
         FROM (SELECT~~)
*/
SELECT *
FROM (SELECT * FROM emp);

-- 각부서의 급여의 최대값을 구하는 SQL
SELECT e.deptno, dname,sal
FROM (SELECT deptno,MAX(sal) sal
      FROM emp
      GROUP BY deptno) e,dept d
WHERE e.deptno=d.deptno;
-- SELECT 문장 (데이터 검색, 테이블 대신(인라인뷰),컬럼 대신(스칼라 서브쿼리) 사용이 가능)
-- rownum : 오라클에서 지원 => 저장될때 각 ROW마다 번호 설정 
-- rownum을 이용을 이용하는 프로그램 (Top-N:인기순위 10개..), 페이지 나누기, 게시판,영화(상세보기 => 다음보기)
-- rownum은 중간에 빠지는 번호가 없다 
SELECT empno,ename,job,hiredate,sal,rownum
FROM emp_test;
-- 연습 => COMMIT을 사용하면 ROLLBACK을 사용 할 수 없다 
DELETE FROM emp_test
WHERE empno=7499;
ROLLBACK;

-- 5개를 가지고 온다 
SELECT empno,ename,job,hiredate,sal,rownum
FROM emp_test
WHERE rownum<=5;

-- 상위 5개 => 평점 5개 , 인기순위(hit가 많은 거)... 
-- 급여가 많은 사원 순으로 출력 
SELECT ename,sal,rownum
FROM emp_test;

SELECT ename,sal,rownum
FROM emp_test
WHERE rownum<=5
ORDER BY sal DESC;

SELECT ename,sal,rownum
FROM (SELECT ename,sal FROM emp ORDER BY sal DESC) -- rownum의 순서 변경
WHERE rownum<=5;

-- 단점 : rownum을 이용해서 원하는 부분만 데이터 출력에 (위에서 몇개는 가능 , 중간에 자르는 것응 불가능)

SELECT ename,sal,rownum
FROM (SELECT ename,sal FROM emp ORDER BY sal DESC) -- rownum의 순서 변경
WHERE rownum BETWEEN 1 AND 5;

SELECT ename,sal,rownum
FROM (SELECT ename,sal FROM emp ORDER BY sal DESC) -- rownum의 순서 변경
WHERE rownum BETWEEN 6 AND 10;
-- 필수적으로 본다 
-- 복합뷰 , 단순뷰 (컬럼이 많이 있는 경우 => SQL문장을 줄이기 위해서 보통 사용 
SELECT ename,sal,num
FROM (SELECT ename,sal,rownum as num 
      FROM (SELECT ename,sal FROM emp ORDER BY sal DESC)) -- rownum의 순서 변경
WHERE num BETWEEN 11 AND 14;

-- 영화 => movie (title, actor, director, score,poster) => 1938 => 20개 정도 (사람이 한눈에 볼 수 있는 15~20)
SELECT title,actor,director,mno,rownum
FROM movie;

SELECT mno,title,rownum
FROM movie;

SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC);

SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)
WHERE rownum<=10;

SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)
WHERE rownum BETWEEN 1 AND 1938;

SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)
WHERE rownum BETWEEN 21 AND 40;

SELECT mno,title,num
FROM (SELECT mno,title,rownum as num
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)) -- rownum을 한개 컬럼으로 인식=> 제어
WHERE num BETWEEN 21 AND 40;

SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)
WHERE mno=1;
SELECT mno,title,rownum
FROM (SELECT mno,title FROM movie ORDER BY mno ASC)
WHERE mno=2;
-- 컬럼값은 데이터가 삭제될때 없어진다 , rownum은 데이터가 삭제될때 번호삭제되는 것이 아니라 => 위로 당겨준다 
-- ArrayList
-- MView => 권한이 없다 (hr/happy: 사용자)
-- 1. MView
CREATE MATERIALIZED VIEW m_emp2
BUILD IMMEDIATE -- MView를 생성하는 즉시 서브쿼리 (AS 밑에 있는 문장을 수행하고 => 데이터를 MView에 저장)
REFRESH
ON DEMAND -- 동기화 (원본 데이터) => View를 갱신한후에 원본데이터를 변경
COMPLETE -- 동기화 범위가 전체 
AS
 SELECT * FROM emp;
 
SELECT * FROM m_emp2;
-- page 412 : 가상 테이블 (저장된것은 데이터가 아니라 SELECT~문장이 저장되어 있다) 
-- page 413 : 가상(메모리에 실제 데이터가 존재하지 않기 때문에 => 해킹(X) 보안이 좋다)
-- 속도가 늦다 : 사용자 요청 ==> View의 Select를 수행 => 원본테이블
-- 주로 사용 : 검색 (실무에서 활용도가 많은 업체 , 사용하지 않는 업체도 있다)
-- page 414 : 종류 (단순뷰) : => XE(권한이 부여되어 있다)
/*
    권한 : => 사용 권한 : SYSTEM,SYSDBA (데이터베이스 관리자) , hr은 사용자 계정
          conn SYSTEM/happy
          conn / as SYSDBA 
          => GRANT CREATE VIEW TO hr
    단순뷰 : 한개의 테이블만 연결 
            형식) CREATE [OR REPLACE] VIEW view_name
                 AS 
                    SUBQUERY (SELECT ~~)
            => DML을 사용할 수 있다 (page 416)
            DML(INSERT,UPDATE,DELETE) => 원본 테이블에 문제가 발생 할 수 있다 
            => 방지 : WITH READ ONLY => SELECT만 사용이 가능 하게 만든다 
    page 419 : 복합뷰 (여러개 테이블 연결) => 집합연산자(가급적 사용금지 권장),JOIN =>View를 사용하면 SQL문장을 만들기가 쉽다
               SELECT * FROM [teble_name|view_name|SELECT~]
               => 프로그램에서 사용빈도(비슷한 쿼리문장이 많은 경우에 주로 사용)
               => 목록(JOIN),상세보기 ... 
    page 421 : 인라인뷰 (View를 생성하지 않고 select문장을 이용해서 데이터를 가지고 오는 SQL)
               형식) 
                    SELECT ~ 
                    FROM (SELECT~) => rownum을 이용(페이지 나누기)
                    rownum : 오라클에서 자동으로 지정하는 번호 (빠지는 번호가 없다)
                    저장된 순서로 (저장된 메모리 순서)
    page 425 : MView : 구체화된 뷰 (뷰안에 데이터값을 채워 놓고 시작)
    
*/


우선 View의 목적 자체는 보여주기만을 위한 기능이다. 테이블을 참조해서 view를 만들어 주고, 그 가상테이블을 이용해서 필요한 데이터만 모아서 정리해줄때 사용하면 된다. 

 

CREATE [OR REPLACE] VIEW view_name
           AS
            SELECT empno,ename,hiredate,sal,dname,loc
            FROM emp,dept
            WHERE emp.deptno=dept.deptno; 

 이렇게 코드를 이용해서 view를 생성해준다. 그러면 java에서 view를 이용할때는 view_name만 이용해서 데이터를 처리할 수 있다는 장점을 갖는다. 

 

뷰에서 가장 중요한 파트는 '인라인뷰'이다. 웹에서 페이징기법을 사용할때 이용되기 때문이다. 

 ***3) 인라인 뷰 : 테이블 대신 SELECT 문장을 이용해서 주로 처리 (페이징기법)
          CREATE [OR REPLACE] (X)
          SELECT * (설정된 컬럼을 벗어날 수 없다
          FROM (SELECT ~) => 보안
                ======== 설정한 컬럼
            
              => SubQuery => 반드시 (subquery) :()안 문장 먼저 실행=> 다른 SQL문장을 실행
          예) SELECT empno,ename,job,hiredate,sal    ==> 오류 
              FROM (SELECT empno,ename,job,sal,comm,deptno => hiredate가 존재하지 않았다
                    FROM emp);
              => FROM (SELECT~)
                      ========= 반드시 ()를 사용한다 

 

-- 각부서의 급여의 최대값을 구하는 SQL
SELECT e.deptno, dname,sal
FROM (SELECT deptno,MAX(sal) sal
      FROM emp
      GROUP BY deptno) e,dept d
WHERE e.deptno=d.deptno;

 이런식으로 서브쿼리를 이용해서 인라인뷰를 사용할 수 있다. 

 

인라인뷰가 페이징 기법에서 가장 많이 사용되고 있기 때문에 어떤 식으로 페이징이 되고 있는지 이해하는 것이 가장 중요하다고 한다. 

 

오라클에서 제공하는 rownum 기능을 통해서 페이징을 나눠볼 수 있다. rownum은 저장될때 각 row마다 번호를 설정해주는 기능이다. 

SELECT empno,ename,job,hiredate,sal,rownum
FROM emp_test
WHERE rownum<=5;

 

 이런식으로 사용하면 상위 rownum을 가진 5개 데이터를 선택하여 가지고 올 수 있다. 

하지만 rownum이 매겨지는건 데이터가 저장되는 순서이기 때문에 어떤 컬럼에 해당하는 값을 기준으로 정렬하기가 힘들다. 그래서 급여순으로 rownum을 가져오기 위해서는 아래와 같이 코드를 작성해주어야 한다. 

SELECT ename, sal, rownum
FROM (SELECT ename, sal FROM emp ORDER sal BY DESC)
WHERE rownum<=5;

 

 하지만 이렇게 써줄 경우에 위에서부터 혹은 밑에서부터 값을 가져오는 것은 가능하지만, 중간에서부터 값을 가져오는 것은 불가능하다. 그렇기 때문에 아래와 같이 SubQuery를 한 번 더 사용해서 써주어야 한다. 

SELECT ename,sal,num
FROM (SELECT ename,sal,rownum as num 
      FROM (SELECT ename,sal FROM emp ORDER BY sal DESC)) -- rownum의 순서 변경
WHERE num BETWEEN 11 AND 14;

 

데이터가 더 많았던 MOVIE 테이블을 사용해서 rownum 활용을 더 연습해보도록 하겠다

mno순으로 중간부터 값을 가져 올 수 있는 코드를 한 번 작성해보면, 

SELECT mno, title, actor, director, num 
FROM (SELECT mno, title, actor, director, rownum as num
		FROM(SELECT mno, title, actor, director FROM movie ORDER BY mno ASC))
WHERE mno BETWEEN 50 AND 100;

mno는 반드시 모든 SELECT 문에 포함되어 있어야 한다. 

 

 

다음은 Subquery를 배웠다. 

--2021-02-22 SubQuery
/*
    JOIN : (한개 이상) 여러개의 테이블에서 필요한 데이터를 모아서 관리 (저당된 데이터와 관련)
                => SELECT에서만 사용
    SubQuery : SQL문장을 합쳐서 데이터를 가지고 온다 (자바에서 많이 사용)
                => SELECT, INSERT, UPDATE, DELETE에서 사용이 가능
                브라우저 =============> 자바 =============> 오라클
                            요청             SQL문장 만들어서 전송 
                            
                브라우저 <============= 자바 <============= 오라클
                            데이터를 모아서 SQL실행된 데이터 전송
                         ======================================= 네트워크 프로그램(최대한 패킷을 한번에 전송)
    사용하는 위치) 테이블 대신 사용이 가능, 컬럼대신 사용이 가능 
    
    서브쿼리 사용 방식)
                SELECT * FROM emp
                ================= 메인쿼리
                WHERE empno=(SELECT~)
                             ========= 서브쿼리
                1. 서브쿼리가 먼저 실행 => 결과값 => 메인 쿼리로 전송해서 실행
    
    종류 
     = 단일행 서브쿼리 : 결과값이 1개면
     = 다중행 서브쿼리 : 결과값이 여러개면 
     = 스칼라 서브쿼리 : 컬럼 대신 사용하는 방식 
     = 다중 컬럼 서브쿼리 (사용빈도가 거의 없다) : 컬럼값이 여러개
     = With절을 이용한 서브쿼리
*/
SELECT sal FROM emp WHERE empno=7788; -- 단일행
SELECT sal FROM emp; -- 다중행
SELECT sal, comm FROM emp WHERE empno=7788; -- 다중컬럼

-- 문제 : SCOTT 사원과 같은 부서에서 근무하는 사원의 이름, 입사일, 직위 출력
/*
    SCOTT => deptno
    deptno => 같은 부서의 사원
*/

SELECT deptno FROM emp WHERE ename='SCOTT';
SELECT ename, hiredate, job FROM emp WHERE deptno=20;

-- 한개의 sql문장으로 변경 => 서브쿼리
 SELECT ename, hiredate, job FROM emp
 WHERE deptno=(SELECT deptno FROM emp  WHERE ename='SCOTT');

-- emp에서 평균급여보다 작게 받는 사원의 이름, 급여, 입사일을 출력
-- 평균급여 구하는게 첫번째 SubQuery 
-- 1. 평균 급여 구하기
SELECT ROUND(AVG(sal), 0) 
FROM emp;

--SQL문장 합치기 
SELECT ename, sal, hiredate FROM emp
WHERE sal<(SELECT ROUND(AVG(sal), 0) FROM emp);

-- DML 전체에서 사용이 가능 => SQL문장이 복잡해 진다 (JOIN, SUBQUERY)

 서브쿼리는 전부터 연습해오기도 했고 오늘 배운 내용이 그렇게 어렵지 않았어서 가볍게 정리만 하고 넘어가겠다. 

 

-- SUBQUERY 문제 
/*

	
*/
--부서명이 SALES 부서사원 중 가장 많은 급여를 받는 사원의 급여는?
SELECT MAX(sal)
FROM emp
WHERE deptno=(SELECT deptno FROM dept WHERE dname='SALES');

--SMITH 보다 월급을 많이 받는 사원들의 이름과 월급을 출력하라?
SELECT ename, sal
FROM emp
WHERE sal>(SELECT sal FROM emp WHERE ename='SMITH');

--10번 부서의 사원들과 같은 직위를 가진 사원들의 이름과 월급과 부서번호를 출력하라.
SELECT ename, sal, deptno
FROM emp
WHERE job IN(SELECT DISTINCT job FROM emp WHERE deptno=10) AND deptno <> 10;
-- 다중행 서브쿼리 (결과값이 여러개 있다 => 전체 대입)

--BLAKE와 같은 부서에 있는 사람들의 이름과 입사일을 출력하되 BLAKE는 제외
SELECT ename, hiredate
FROM emp
WHERE deptno=(SELECT deptno FROM emp WHERE ename='BLAKE')
AND ename NOT LIKE 'BLAKE';

--평균 급여보다 많은 급여를 받는 사원들의 사번, 이름, 월급을 나타내되 월급이 높은 사람 순으로 출력하라?
SELECT empno, ename, sal
FROM emp
WHERE sal>(SELECT AVG(sal) FROM emp) 
ORDER BY 3 DESC;

--이름에 T를 포함하고 있는 사원들과 동일한 부서에서 근무하고 있는 사원의 사원 번호와 이름을 출력하라?
SELECT empno, ename 
FROM emp
WHERE deptno IN(SELECT deptno FROM emp WHERE ename LIKE '%T%');

--30번 부서의 최고 급여를 받는 사원보다도 더 많은 급여를 받는 전체 사원들을 출력하라
SELECT *
FROM emp
WHERE sal>(SELECT MAX(sal) FROM emp WHERE deptno=30);

--부서 위치가 DALLAS인 모든 사원의 이름, 부서번호 및 직업을 출력하라.
SELECT ename, deptno, job
FROM emp
WHERE deptno = (SELECT deptno FROM dept WHERE loc='DALLAS');

--SALES 부서의 모든 사원에 대한 부서번호, 이름 및 직업을 출력하라?
SELECT deptno, ename, job
FROM emp
WHERE deptno=(SELECT deptno 
FROM dept
WHERE dname='SALES');
	

SELECT * FROM emp_test;

-- 사원 추가 => empno (Primary key) => 서브쿼리 이용해서 처리
/*
    1. 스칼라 서브쿼리 
    2. DML에서 사용 => PRIMARY 값을 구하는 경우 (자동 증가)
    3. 모든 DML에서 사용이 가능 (INSERT, UPDATE, DELETE)
    
*/

-- 자동 증가 번호 (PRIMARY KEY)
-- 데이터가 없는 경우 
INSERT INTO emp_test2 VALUES(
    (SELECT NVL(MAX(empno)+1, 1) FROM emp_test2), '홍길동', '대리', 7780, SYSDATE, 3000, 200, 40);


SELECT * FROM emp_test;

CREATE TABLE emp_test2
AS 
    SELECT * FROM emp WHERE 1=2;
SELECT * FROM emp_test2;

DELETE FROM emp_test2;
COMMIT;

-- UPDATE 사용 => SMITH가 있는 부서에 모든 사원의 급여를 10% => sal*1.1
UPDATE emp_test SET 
sal=sal*1.1
WHERE deptno = (SELECT deptno FROM emp WHERE ename='SMITH');

SELECT * FROM emp_test;

-- DELETE BLAKE 퇴사 => 30번에 모든 사원 퇴사
DELETE FROM emp_test
WHERE deptno=(SELECT deptno FROM emp_test WHERE ename ='BLAKE');

/*
    다중행
    전체 사용 => IN (10,20,30)
    최대값 => MAX(10,20,30)
    최소값 => MIN(10,20,30)
*/

 위의 문제들은 내가 직접 풀었다. 이정도의 응용은 아직 어렵지는 않은데..

다음시간에 시퀀스와 인덱스를 배운다고 하는데 어려울것 같아서 미리 걱정되는 중이다. 

 

 

아래 코드는 view를 이용해서 어떻게 자바와 오라클을 연동하여 활용할 수 있는지 보여주는 코드이다. 

package com.sist.dao;
import java.sql.*;
import java.util.*;
// 언제 뷰생성하는 것이 적당하지 여부
public class ViewDAO {
    // 연결
	private Connection conn;
	// SQL문장을 전송 
	private PreparedStatement ps;
	// 오라클 연결 
	private final String URL="jdbc:oracle:thin:@localhost:1521:XE";
	// 드라이버 등록
	public ViewDAO()
	{
		try
		{
			Class.forName("oracle.jdbc.driver.OracleDriver");
			// Class.forName() => 등록된 클래스의 메모리 할당 (new) => 클래스 정보를 읽어서 관리 : 리플렉션
			// 메소드 제어 , 멤버변수,생성자, 매개변수를 제어 할 수 있다 
			// 예외처리(CheckException:컴파일시 검사=반드시 예외 처리) => ClassNotFoundException
		}catch(Exception ex){}
	}
	// 오라클에 연결 
	public void getConnection()
	{
		// conn hr/happy
		try
		{
			conn=DriverManager.getConnection(URL,"hr","happy");
		}catch(Exception ex) {}
	}
	// 오라클 연결 종료
	public void disConnection()
	{
		// exit
		try
		{
			if(ps!=null) ps.close(); // 연결중이면 
			if(conn!=null) conn.close();
		}catch(Exception ex) {}
	}
	// 기능 (목록) => SQL문장 , View를 이용 
	/*
	 *   SELECT empno,ename,job,hiredate,sal,dname,loc,grade
		  FROM emp,dept,salgrade
		  WHERE emp.deptno=dept.deptno
		  AND sal BETWEEN losal AND hisal
	 */
	public void empAllData()
	{
		try
		{
			// 1. 연결
			getConnection();
			// 2. SQL문장 제작 
			/*
			 * String sql="SELECT empno,ename,job,hiredate,sal,dname,loc,grade " +
			 * "FROM emp,dept,salgrade " + "WHERE emp.deptno=dept.deptno " +
			 * "AND sal BETWEEN losal AND hisal";
			 */
			String sql="SELECT * FROM emp_dept_view ORDER BY empno ASC";
			// 3. 오라클에 전송 
			ps=conn.prepareStatement(sql); // conn이 오라클하고 연결된 객체
			// 4. 오라클 실행 결과를 받아 온다 
			ResultSet rs=ps.executeQuery();
			// 5. 결과값 출력 => ResultSet => 단위가 Record => empno,ename,job,hiredate,sal,dname,loc,grade
		    while(rs.next())
		    {
		    	System.out.println(rs.getInt(1)+" "
		    			+rs.getString(2)+" "
		    			+rs.getString(3)+" "
		    			+rs.getDate(4)+" "
		    			+rs.getInt(5)+" "
		    			+rs.getString(6)+" "
		    			+rs.getString(7)+" "
		    			+rs.getInt(8));
		    }
		    rs.close();
		}catch(Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		finally
		{
			disConnection();
		}
	}
	// 상세보기 
	public void empDetailData(int empno)
	{
		try
		{
			// 1. 연결
			getConnection();
			// 2. SQL문장 제작
			/*String sql="SELECT empno,ename,job,hiredate,sal,dname,loc,grade "
					+ "FROM emp,dept,salgrade "
					+ "WHERE emp.deptno=dept.deptno "
					+ "AND sal BETWEEN losal AND hisal "
					+ "AND empno=?";*/
			String sql="SELECT * FROM emp_dept_view "
					  +"WHERE empno=?";
			// View => SELECT의 모든 기능을 사용 할 수 있다 (GROUP BY,WHERE,ORDER BY)
			// View도 일반 테이블처럼 사용이 된다 
			ps=conn.prepareStatement(sql);
			// ?에 값을 채운다 
			ps.setInt(1, empno);
			// 3. 실행요청
			ResultSet rs=ps.executeQuery();
			// 커서위치 변경 => 데이터가 있는 위치로 지정 => next()
			rs.next();
			// 4. 결과값 출력 => 브라우저 (VO에 값을 채운다)
			System.out.println(rs.getInt(1)+" "
	    			+rs.getString(2)+" "
	    			+rs.getString(3)+" "
	    			+rs.getDate(4)+" "
	    			+rs.getInt(5)+" "
	    			+rs.getString(6)+" "
	    			+rs.getString(7)+" "
	    			+rs.getInt(8));
			rs.close();
		}catch(Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		finally
		{
			disConnection();
		}
	}
	// 페이지 나누기 => movie 
	public void movieListData(int page) // 사용자가 보내준 페이지를 받아서 해당 페이비만 전송 
	{
		try
		{
			// 1. 연결
			getConnection();
			String sql="SELECT mno,title,num "
					  +"FROM (SELECT mno,title,rownum as num "
					  +"FROM (SELECT mno,title "
					  +"FROM movie ORDER BY mno ASC)) "
					  +"WHERE num BETWEEN ? AND ?";
			ps=conn.prepareStatement(sql);
			// ?에 값을 채운다 
			int rowSize=20;
			int start=(page*rowSize)-(rowSize-1);
			int end=rowSize*page;
			
			/*
			 *   1page : 1~20
			 *   2page : 21~40  ==> rownum은 1번 시작 
			 *   ..
			 *   ..
			 */
			ps.setInt(1, start);
			ps.setInt(2, end);
			
			// 실행 요청
			ResultSet rs=ps.executeQuery();
			while(rs.next())
			{
				System.out.println(rs.getInt(1)+". "+rs.getString(2));
			}
			rs.close();
		}catch(Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		finally
		{
			disConnection();
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        ViewDAO dao=new ViewDAO();
        //dao.empAllData();
        //dao.empDetailData(7788);
        Scanner scan=new Scanner(System.in);
        System.out.print("페이지 설정:");
        int page=scan.nextInt();
        dao.movieListData(page);
	}

}
728x90
반응형