오늘은 Oracle SQL 마지막날~
<금일 교육 내용>
사전, 인덱스,시퀀스, 뷰
<주요 일정>
8/18~8/29
- 오라클
- JDBC
- MySQL
8/30~9/5
- JSP&Servlet
<복습>
- Transaction : 하나의 논리적인 실행단위로 처리 (SQL문 -> Java 코드 실행 -> SQL문)
- Commit: Transaction 이후에 반영하는 것.
- Rollback : Transaction 이전 상태로 되돌리는 것.
- Checkpoint : 라벨을 붙여서 Transaction -> Commit 사이에서 잘 반영이 됐는지 체크해주는 기능
자바코드를 이용하면 체크포인트를 거의 사용하지 않음.
- DDL : CRUD 연산에 이용되는 SQL은 DML이라고 부르고(select, insert, update, delete)(Data의 내용을 핸들링함)(Transaction의 관리대상),
객체 자체(Table, User, View, Index 등)를 핸들링 하는 것을 DDL이라고 부름.
Data Definition Language의 약어임.
가장 대표적인 예시 : create 객체종류 대상이름, alter 객체종류 대상이름, drop 객체종류 대상이름
alter user scott identified by ~~; => 비밀번호 변경 예시
- 컬럼의 데이터 타입 : 제품별로 데이터 타입이 다르므로 따로 정리하는 것이 좋음.
* NUMBER(w,d) -> 숫자 길이에 제한이 없음. 제한하면 13자리
* CHAR() : 필수정보. 고정길이를 가짐. 주로 우리가 다루는 데이터의 길이가 정해진 경우에 사용한다.
* VARCHAR2() : 필수정보. 길이에 제한이 없음. 조금이라도 길이가 길어질 수 있는 것들은 모두 varchar2()를 사용한다. 최대 값은 2000이며, byte 단위이다. 한글을 저장한다고 가정한다면, 한글은 한자당 3byte이므로 700자밖에 넣을 수 없다.
* DATE() : 날짜 정보를 넣을 때 사용.
* LONG() : 아주 긴 데이터를 넣을 때 사용.
* LOB() : 아주 긴 데이터를 넣을 때 사용.
- 제약조건 ☆☆☆
* NOT NULL : 생략할 수 없음. 필수 데이터.
* NULL : 비어있는 데이터, Default 값
* UNIQUE : 중복이 안됨. NULL 허용. Key값에 반드시 들어감. Key는 검색작업이 빈번하기 때문에 검색 속도를 낮추기 위해서 INDEX가 자동으로 구축됨.
* PRIMARY KEY(컬럼1, 컬럼2, ...) : NOT NULL + UNIQUE의 기능이 합쳐짐. INDEX가 자동으로 구축됨. 테이블을 만들 때 반드시 프라이머리키를 정의하는 것이 권장됨.
* FOREIGN KEY : 참조를 설정할 떄 씀. child -> parent. 이때 반드시 참조하는 키는 Parent 테이블에서 UNIQUE 속성이거나, PRIMARY KEY 속성이어야 함. 참조하는 키의 값이 반드시 존재하는 데이터여야만 참조된 키에서 해당 데이터를 사용할 수 있음. ON DELETE SET NULL 등의 기능 추가 가능함.
<<본론>>
<데이터 형태와 범위를 정하는 CHECK>
1. CHECK 제약조건
- 테이블을 생성할 때 CHECK 제약조건 설정하기
* true : 성공, false : 실해
* CHECK( 컬럼 IN ('F', 'M')) 이런식으로도 사용 가능
CREATE TABLE TABLE_CHECK(
LOGIN_ID VARCHAR2(20) CONSTRAINT TBLCK_LGNID_PK PRIMARY KEY,
LOGIN_PWD VARCHAR2(20) CONSTRAINT TBLCK_LGNPW_CK CHECK(LENGTH(LOGIN_PWD) > 3),
TEL VARCHAR2(20)
)
- CHECK 제약조건에 맞지 않는 예
INSERT INTO TABLE_CHECK
VALUES('TEST_ID', '123', '010-1234-5678');
- CHECK 제약조건에 맞는 예
INSERT INTO TABLE_CHECK
VALUES('TEST_ID', '1234', '010-1234-5678');
- CHECK 제약조건 확인하기
SELECT OWNER, CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME LIKE 'TABLE_CHECK';
<기본 값을 정하는 DEFAULT>
1. DEFAULT 제약조건
- 테이블을 생성할 때 DEFAULT 제약조건 설정하기
CREATE TABLE TABLE_DEFAULT(
LOGIN_ID VARCHAR2(20) CONSTAINT TBLCK2_LGNID_PK PRIMARY KEY,
LOGIN_PWD VARCHAR(20) DEFAULT '1234',
TEL VARCHAR2(20),
REG_DATE DATE DEFAULT SYSDATE,
UPDATE_DATE DATE DEFAULT SYSDATE
);
=> 보통은 default를 날짜에 자주 이용함
REG_DATE DATE DEFAULT SYSDATE
UPDATE_DATE DATE DEFAULT SYSDATE
- DEFAULT로 지정한 기본값이 입력되는 INSERT문 확인하기
INSERT INTO TABLE_DEFAULT(LOGIN_ID, LOGIN_PWD,TEL) VALUES('TEST_ID', NULL, '010-1234-5678');
INSERT INTO TABLE_DEFAULT(LOGIN_ID,TEL) VALUES('TEST_ID2', '010-1234-5678');
- 디비에서 결국 가장 중요한 것은 PK, FK 이다.
* 1:1
* 1:N
* N:M
=> N:M 관계는 A - 중개테이블 - B 의 구조일때 이뤄질 수 있다.
==> 주로 해시태그, 상품, 카테고리 테이블에서 많이 쓰이는 구조이다.
<데이터베이스를 위한 데이터를 저장한 데이터 사전>
1. 데이터 사전이란?
- DDL 작업 : 관리정보 (관리정보할때 생성되는 특수한 테이블 - 데이터 사전)
- 함부로 만지면 안됨.
- 데이터베이스를 구성하고 운영하는 데 필요한 모든 정보를 저장하는 특수한 테이블
- 데이터베이스가 생성되는 시점에 자동으로 만들어짐
- 데이터베이스 메모리, 성능, 사용자, 권한,
- 데이터 사전 뷰, 용도에 따라 접두어를 달리함
* USER_XXXX : 현재 데이터베이스에 접속한 사용자가 소유한 객체 정보
* ALL_XXXX : 현재 데이터베이스에 접속한 사용자가 소유한 객체 또는 다른 사용자가 소유한 객체 중 사용허가를 받은 객체, 즉 사용 가능한 모든 객체 정보
* DBA_XXXX : 데이터베이스 관리를 위한 정보 (데이터베이스 관리 권한을 가진 SYSTEM, SYS 사용자만 열람 가능)
* V$_XXXX : 데이터베이스 성능 관련 정보(X$_XXXX)
- SCOTT 계정에서 사용 가능한 데이터 사전 살펴보기(DICT 사용)
SELECT * FROM DICT;
=> 약 300개
- SCOTT 계정에서 사용 가능한 데이터 사전 살펴보기(DICTIONARY 사용)
SELECT * FROM DICTIONARY;
=> 약 50개
2. USER 접두어를 가진 데이터 사전
- 사용자가 소유한 객체 정보가 보관
3. ALL_ 접두어를 가진 데이터 사전
- 접속한 계정으로 사용가능한 테이블에 관한 정보
- SCOTT 계정이 사용할 수 있는 객체 정보 살펴보기(ALL_ 접두어 사용)
SELECT OWNER, TABLE_NAME FROM ALL_TABLES;
4. USER_TABLE
5. DBA_ 접두어를 가진 인덱스
<더 빠른 검색을 위한 인덱스>
1. 인덱스란?
- SCOTT 계정이 소유한 인덱스 정보 알아보기(SCOTT 계정일 떄)
select * from USER_IDEXES;
- SCOTT 계정이 소유한 인덱스 컬럼 정보 알아보기(SCOTT 계정일 떄)
select * from user_ind_columns;
- TREE 구조를 자주 사용
* 자식에 대한 참조를 운영
* 새로운 값이 발생했을 때 비교를 통해서 작으면 왼쪽, 크면 오른쪽에 붙인다.
** 맨 오른쪽에 간 값과는 더이상 비교하지 않음. (버림..?)
** 계속해서 값을 비교 비교 비교...
** 알고리즘 수업에서 계속...
2. 인덱스 생성
create index 인덱스 이름
on 테이블 이름(열이름1 asc or desc, 열이름1 asc or desc, ...);
튜닝작업
- EMP 테이블의 SAL 열에 인덱스를 생성하기
create index idx_emp_sal on emp(sal);
- 생성된 인덱스 살펴보기(user_ind_columns 사용)
select * from user_ind_columns;
4. 인덱스 삭제
drop index 인덱스_이름;
- 인덱스 삭제하기
drop index idx_emp_sal;
- 생성된 인덱스 살펴보기(user_ind_columns 사용)
select * from user_ind_columns;
<테이블처럼 사용하는 뷰>
1. 뷰(View) 란?
- 가상 테이블
- 하나 이상의 테이블을 조회하는 select 문을 저장한 객체
- 물리적 데이터를 따로 저장하지 않음
- 복잡한 select문을 간결히 처리하기 위함
- 뷰 : select * from vw_emp20;
- 서브쿼리 : select * from(select...)
2. 뷰의 사용 목적
- 편리성 : select 문의 복잡도를 완화
- 보안성 : 테이블의 특정 열을 노출하고 싶지 않을 경우
3. 뷰 생성
- 뷰 생성 권한이 없는 경우, 권한 부여 필요(SYS 계정으로 작업)
GRANT CREATE VIEW TO SCOTT;
create [or replace] [force | noforce] view 뷰 이름 (열 이름1, 열 이름2, ...)
- 뷰 생성하기
create view vm_emp20
as (select empno, ename, job, deptno
from emp
where deptno = 20);
select * from user_views;
- 생성한 뷰 조회하기
select * from vw_emp20;
4. 인라인 뷰를 사용한 TOP-N SQL문
- 인라인 뷰 inline view
* SQL문에서 일회성으로 만들어서 사용하는 뷰
- ROWNUM
* SELECT 문의 결과 행에 순서대로 붙이는 정수
* 가상 컬럼, pseudo column
- ROWNUM을 추가로 조회하기
select rownum, e.* from emp e;
select rownum, e.* from emp e order by sal;
==> 오름차순
===> 기대했던 값이 안나옴. 왜? : select로 먼저 리스트를 뽑고 난 뒤에 오름차순 정렬을 했기 때문에.
- order by 결과에 rownum 을 붙이면 순위(등수)로 해석 가능
- 인라인 뷰(서브쿼리 사용)
select rownum, e.*
from (select * from emp e order by sal desc) e;
- 상위 n개 추출하기 -> top-n 문제
- 인라인 뷰로 top-n 추출하기(서브쿼리 사용)
select rownum, e.* from (select * from emp e order by sal desc) e WHERE rownum <=3;
그러나, 다음과 같은 쿼리문은 안됨.
select rownum, e.* from (select * from emp e order by sal desc) e WHERE rownum >3;
select rownum, e.* from (select * from emp e order by sal desc) e WHERE BETWEEN 3 AND 5;
- 페이지네이션을 만들 때 사용됨. : 1페이지는 나올 수 있지만, 이런식으로 하면 2페이지 후부터는 안나옴.
==> 이럴때는 뷰를 만들어서 사용하면 페이지네이션 기능을 사용할 수 있음.
select row_number() over(order by sal desc) seq, e.* from emp e;
create view emp_sal_rank
as
select row number() over(order by sal desc) seq, e.* from emp e;
SELECT * FROM EMP_SAL_RANK WHERE seq BETWEEN 3 AND 5;
==> 이렇게 하면 2페이지도 뽑아낼 수 있다. 그리고 그 다음 페이지도 가능하다.
SELECT * FROM EMP_SAL_RANK WHERE seq > 5;
==> 5 이후의 숫자도 뽑아낼 수 있다.
====> 이 방법은 oracle만의 독특한 운영방식이다. 하지만 mysql로 하면 좀 더 편하게 구간을 뽑아낼 수 있다.
만약에 db에서 페이지네이션 처리를 해줘야 한다면
SELECT * FROM EMP_SAL_RANK WHERE seq BETWEEN 4 AND 4+2;
이런식으로 계산식이 들어가서 페이지네이션 처리를 하게 될 것이다.
같은 테이블명으로 새로 테이블을 만들면 에러가 남.
그래서 drop하고 다시 만들어야 하는데,
테이블을 일일히 다 못보는 경우가 많으므로
create or replace view emp_sal_rank ~~~
이런식으로 or replace를 안전장치로 넣어줘서
'만약에 이 테이블이 있다면 이 테이블을 다음처럼 바꿔서 재생산 해달라~' 라는 의미로
테이블을 재생산 할 수 있다.
<문제>
-- SAL로 내림차순 정렬
-- SEQ, EMPNO, EMPNAME, DEPTNO, DNAME을 가지는 뷰
1) 일단, 오름차순과 내림차순 모두 가능하도록 뷰를 생성함.
CREATE OR REPLACE VIEW EMP_DETAIL
AS
SELECT ROW_NUMBER() OVER(ORDER BY SAL DESC) SEQ, E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E JOIN DEPT D ON (E.DEPTNO = D.DEPTNO);
2) 뷰를 내림차순으로 select 함
SELECT * FROM EMP_DETAIL
ORDER BY SEQ DESC;
3) 끝
<규칙에 따라 순번을 생성하는 시퀀스>
1. 시퀀스란?
- sequence (객체임.. 테이블, 인덱스, 뷰와 같은 레벨 -> 오라클에만 있는 개념)
- 특정 규칙에 맞는 연속 숫자를 생성하는 객체
- 은행의 대기 순번표와 유사
create sequence 시퀀스 이름 //명명관계 : 테이블명_SEQ 이런식으로
[increments by n]
[start with n] //몇번부터 시작할거냐
[maxvalue n | nomaxvalue] //최대값지정, 일반적으로는 max 값을 안줌
[minvalue n | nominvalue] //최소값지정
[cycle | nocycle] //최대값까지 도달한 후 그 값을 넘었을 때 다시 최소값으로 감
[cache n | nocache] //최대값까지 도달한 후 그 값을 넘었을 때 에러가 발생하게끔 함
2. 시퀀스 생성
- 실습 준비
create table dept_sequence as select * from dept where 1 <> 1;
- 시퀀스 생성하기
CREATE SEQUENCE SEQ_DEPT_SEQUENCE
INCREMENT BY 10
START WITH 10
MAXVALUE 90
MINVALUE 0
NOCYCLE
CACHE 2;
SELECT * FROM USER_SEQUENCES;
3. 시퀀스 사용
- 시퀀스이름.CURRVAL
* 마지막으로 생성한 번호를 반환
- 시퀀스이름.NEXTVAL
* 다음 번호를 생성
- 시퀀스에 생성한 순번을 사용한 INSERT문 실행하기
INSERT INTO DEPT_SEQUENCE(DEPTNO, DNAME, LOC)
VALUES(SEQ_DEPT_SEQUENCE.NEXTVAL, 'DATABASE', 'SEOUL');
SELECT * FROM DEPT_SEQUENCE ORDER BY DEPTNO;
- 가장 마지막으로 생성된 시퀀스 확인하기
SELECT SEQ_DEPT_SEQUENCE.CURRVAL FROM DUAL;
4. 시퀀스의 마지막까지 오면 더이상 발급되지 않음 -> 발급하면 에러 발생
5. 시퀀스 수정
-시퀀스 옵션 수정하기
ALTER SEQUENCE SEQ_DEPT_SEQUENCE
INCREMENT BY 3
MAXVALUE 99
CYCLE;
SELECT * FROM USER_SEQUENCES;
6. 시퀀스 삭제
drop sequence seq_dept_sequence;
- STORED PROCEDURE : 함수 만드는 것. 데이터베이스마다 자체적인 프로그램이 있음. (오라클에서는 PLSQL)
데이터베이스 내에서만 돌릴 수 있는 프로그램 랭귀지
주로 DB개발자들이 많이 사용하므로 웹개발자들이 알 필요는 없는 내용들임.
<<JDBC>>
<JDBC 프로그래밍>
1. 데이터베이스 준비
- sys 계정 작업
CREATE USER jdbc_ex IDENTIFIED BY jdbc_ex
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP;
GRANT CONNECT, RESOURCE, DBA TO jdbc_ex;
1. JDBC Java Database Connectivity
- 데이터베이스와 연결해서 입출력을 지원
- 데이터베이스 관리시스템(DBMS)의 종류와 상관없이 동일하게 사용할 수 있는 클래스와 인터페이스로 구성
2. JDBC
- JDBC 개념
- JDBC 드라이버 안에 구현클래스가 있음.
3. ojdbc 드라이버 연결
- C:\sqldeveloper\jdbc\lib\ojdbc11.jar
4. JDBC의 핵심 인터페이스/클래스
5. DB연결
- 드라이버 확인
Class.forName("oracle.jdbc.OracleDriaver");
=> 없으면 ClassNotFoundException 발생
- Connection 객체
* 데이터베이스에 연결 세션을 만듦
* Connection conn = DrivaerManager.getConnection("연결문자열", "사용자", "비밀번호);
* 연결문자열
** jdbc:oracle:thin:@localhost:1521/orcl
6. Statement
- SQL문 실행 클래스
- Connection 객체를 통해 생성
Statement stmt = conn.createStatement();
- SQL 실행 메서드
* ResultSet executeQuery(SQL문) : select문(=query문) 실행
* int executeUpdate(SQL문) : insert, update, delete문 실행 // int(=영향받은 row 갯수)
7. ResultSet (Iterator 패턴)
- 컬럼 값 추출
* getXxxx("컬러명)
- Xxx : 추출하고자 하는 데이터 타입명
- getString(), getInt(), getLong(), getDouble()
8. Statement로 Inser문 실행하기
String sql = "INSERT INTO USERS(ID, PASSWORD, NAME, ROLE)" + "VALUES('member2', 'member123', '일반회원', 'USER')";
int count = stmt.executeUpdate(sql);
- 값을 변수로 대체한다면?
String userId = "member2";
String password = "member123";
String name = "일반회원";
String role = "USER";
...
=> PreparedStatement(=실행계획이 이미 다 잡혀있다는 의미임)로 처리
- SQL문에 값을 넣을 때 파라미터화 해서 처리
String sql = "INSERT INTO USERS(ID, PASSWORD, NAME, ROLE) " + "VALUES(?, ?, ?, ?)";
//주의사항 : "INSERT INTO USERS(ID, PASSWORD, NAME, ROLE) " 에서 큰 따옴표로 끝맺기 전에 반드시 스페이스(" ")를 해줘야 함.
- Connection 객체를 통해 생성
PreparedStatement pstmt = conn.preparedStatement(sql);
- 파라미터 설정
* pstmt.setXxxx(파라미터번호, 값)
** setString(), setInt(), setLong(), setDouble()
- SQL문 실행
int count = pstmt.executeUpdate();
8. VO 패턴
- VO 객체
* Value Object
* 특정 테이블의 한 행을 맵핑하는 클래스
Table 정의 = 데이터 클래스 정의(VO)
클래스 정의 -> 테이블
필드들 -> 칼럼들
인스턴스 -> 한 행
9. DAO 패턴 적용
- DAO 클래스
<JUnit>
1. JUnit (메서드검증용)
- 단위 테스트 도구
- 외부 테스트 프로그램(케이스)을 작성하여 System.out으로 번거롭게 디버깅하지 않아도 되며, 테스트에 걸린 시간도 관리 가능
- 보이지 않고 숨겨진 단위 테스트를 끌어내어 정형화시켜 단위 테스트를 쉽게 해주는 테스트용 Framework 입니다.
- JUnit의 특징
* 단위테스트 Framework 중 하나
* 어노테이션으로 간결하게 지원함
* 단정문으로 테스트 케이스
*
2. JUnit관련 어노테이션
- @Test
* 메서드 위에 선언, 테스트 대상 메소드임을 의미
- @Test(timeout=5000)
* 테스트 결과를 반환하는데 5초를 넘기면 테스트 실패로 간주
* 단위는 ms
- @Test(expected=RumtimeException.class)
* RuntimeException이 발생해야 테스트 성공
* 그렇지 않으면 실패로 간주
- @BeforeClass, @AfterClass
* 해당 테스트 클래스
3. 단정문
- assertArrayEquals(expected, actual, message)
- assertEquals(expected, actual, message)
- assertSame(expected, actual, message)
- assetTrue(actual, message)
- assertNotNull(actual, message)
* 실제값과 기대값을 조사하고
'멀티캠퍼스 > DB' 카테고리의 다른 글
20230824 (목) (0) | 2023.08.24 |
---|---|
230822 (화) (0) | 2023.08.22 |
20230821(월) (0) | 2023.08.21 |
20230818 (금) (0) | 2023.08.18 |