2015년 10월 30일 금요일

151012 - DB 의 정규화 / 팀프로젝트

데이터 모델링
---------------------
미팅 
요구사항 수집
요구사항 정리
         -ERD(Entity Relation Diagram)
               -개념적 설계
               -논리적 설계 : 개념적 설계 + 테이블 사상
               -물리적 설계 : 실제 DBMS
구현
디버깅
납품
유지보수
--------------
관계
-----
1. 1:1 관계
2. 1:다 관계(다 : 1관계)
3. 다:다 관계
------------
정규화
------
제1정규화
속성값은 반드시 원자값이어야 한다.

제2정규화
기본키가 복합 필드일 경우
모든 키가 아닌 컬럼은 기본키 전체에 의존적이어야 한다.
기본키의 일부분에 의존적이어서는 안된다.

제3정규화
키가 아닌 컬럼은 다른 키가 아닌 컬럼에 의존적이어서는 안된다.

제4정규화
다대다 관계

제5정규화

-----------------------------------------------------------

ERD 작성
1) 식별 관계
- 부모테이블의 기본키 가 자식테이블의 기본키 로 전이되는 관계
- 1 : 1
2) 비 식별 관계
- 부모테이블의 기본키 가 자식테이블의 일반컬럼 으로 전이되는 관계
- 1 : 多

-------------------------------------------------------------

DB프로젝트 산출물
-----------
1. 발표 ppt
- 조원소개
- 역할분담
- 실행화면 캡쳐(3개이상)
2. ERD
- 설계과정에 따른 변화물도 같이제출

3. UML
- CLASS Diagram
- Sequence Diagram
4. 소스
- java
- sql

5. 프로시저 작성시
- 프로시저 설계도(소스포함)
6. 테이블 스키마

*10개 문항을 테스트하여 통과 여부를 통해 조별점수 책정

151012 - 프로시저, 트리거, procedure, trigger

7. 이름을 입력받아 그 직원의 부서명과 급여를 검색하는 프로시저

CREATE OR REPLACE PROCEDURE usp_search(
p_ename IN emp.ename%type,
p_ename OUT dept.dname%type
p_sal OUT emp.sal%type)
IS 
BEGIN
SELECT dname, sal
FROM dept INNER JOIN emp
ON dept.deptno = emp.edptno AND upper (ename) = upper (p_ename);
END;
/

var g_dname varchar2(14)
var g_sal number

SELECT dname, sal
FROM dept INNER JOIN emp
ON dept.deptno = emp.edptno AND upper (ename) = 'scott;

exec usp_search('scott',:g_dname,:g_sal)
print :g_dname
print :g_sal
--------------------------------------------------------------------

8. 전화번호를 입력받아 다시 전화번호를 리턴하는 프로시저

CREATE OR REPLACE PROCEDURE usp_tel(p_tel in out varchar2)
IS
BEGIN
p_tel := substr(p_tel,1,3) || '-' || substr(p_tel,4);
END;
/

var_g_tel varchar2(10);

BEGIN
:g_tel :=1234567;
END
/

exec usp _ tel(:g_tel)
print : g_tel
---------------------------------------------------------------------
=====================================================================

*******트리거 TRIGGER (콜백 메서드)
발단 : 이벤트가 자동적으로 호출되서 사용

1. 이벤트에 의해 자동으로 호출되는 프로시저
-DML (insert, update, delete)
2. 문법
CREATE [OR REPLACE] TRIGGER 트리거명 {BEFORE|AFTER}
트리거 이벤트 ON 테이블명
[반복문]
BEGIN
END;
3. DD(data dictionary) : user_triggers

4. 트리거는 기본적으로 2개의 임시테이블을 가지고 있다.
OLD(:old), NEW(:new)
insert into member values(4, '권율', '수원', '444-4444');
delete from member where id=1;
update member set addr='제주' where id =20

insert 는 new 테이블 사용
delete 는 old 테이블 사용
update 는 old, new 두개의 테이블 다 사용

=====================================================================

*** 실습 

1. emp 테이블 에서 급여를 수정할 ‹š 현재의 값보다 적게 수정할 수 없고, 현재 값보다 10% 이상 높게 수정할 수 없도록 제한하는 트리거 작성

CREATE OR REPLACE TRIGGER tri_sal_update
BEFORE update ON emp
FOR EACH ROW 
WHEN(NEW.sal < OLD.sal or NEW.sal > OLD.sal*1.1)
BEGIN
raise_application_error(-20506,'수정된 값이 범위에 맞지 않음');
END;
/
-------

update emp set sal = 3000 where ename='KING';

drop trigger tri_sal_update;ed;;/


2. emp테이블을 사용할 수 있는 시간은 월요일부터 금요일까지 09시부터 18시까지만 사용할 수 있도록 하는 트리거 작성

create or replace trigger tri_resource
         before update OR insert OR delete on emp
begin
      if to_char(sysdate, 'dy') in('토', '일') or to_number(to_char(sysdate, 'HH24')) not between 9 and 10
      then
      raise_application_error(-20506, '사용시간이 아닙니다.');
      end IF;
END;
/

show recyclebin

insert into emp(empno, ename) values(1000, 'test100');

3. emp 테이블에서 insert, update, delete문장이 하루에 몇건이나 발생하는지 조사하려고 한다. 조사 내용은 emp_audit라는 테이블에 저장하도록 한다. 조사항목은 사용자 이름, 작업구분, 작업시간으로 처리한다.

create table emp_audit(
   e_id   number(5),
   e_name varchar2(5),
   e_gubun varchar2(30),
   e_date date,
   constraint pk_id primary key(e_id)
);

create or replace trigger tri_audit
         after insert or update or delete on emp
begin 
   if inserting then
            insert into emp_audit values(seq_empno.nextval, user, 'insert작업', sysdate);
   elsif updating then
            insert into emp_audit values(seq_empno.nextval, user, 'update작업', sysdate);
   elsif deleting then
            insert into emp_audit values(seq_empno.nextval, user, 'delete작업', sysdate);
   end if;
end;

insert into emp(empno, ename) values(1000, 'test1000');
insert into emp(empno, ename) values(1001, 'test1001');
insert into emp(empno, ename) values(1002, 'test1002');

delete from emp where empno between 1000 and 1002;

select * from emp_audit;

151009 - SQL 과제


해당 테이블 생성하기



계정 생성 후 접속
===========================================

CREATE USER pbs IDENTIFIED by 1111;
GRANT RESOURCE, connect to TEST;
CONN TEST/1111

테이블 post 만들기
===========================================

CREATE TABLE POST(
POST1 CHAR(3),
POST2 CHAR(3),
ADDR VARCHAR2(60)  CONSTRAINT POST_ADDR NOT NULL,
CONSTRAINT PK_POST PRIMARY KEY (POST1, POST2)
);


출력
=================================================


POS POS ADDR
--- --- ------------------------------------------------------------
        경기도 성남시 분당구 정자동


테이블 member 만들기
=================================================

CREATE TABLE MEMBER(
ID   NUMBER(4)   CONSTRAINT MEMBER_PK_ID PRIMARY KEY,
NAME  VARCHAR2(10)  CONSTRAINT MEMBER_NAME NOT NULL,
SEX   CHAR(1)    CONSTRAINT MEMBER_CK_SEX CHECK(sex=1 OR sex=2),
JUMIN1  CHAR(6),
JUMIN2  CHAR(7),
TEL   VARCHAR2(15),
POST1  CHAR(3),
POST2  CHAR(3),
ADDR  VARCHAR2(60),  
CONSTRAINT MEMBER_UK_JUMIN UNIQUE (JUMIN1, JUMIN2),
CONSTRAINT MEMBER_FK_POST FOREIGN KEY (POST1, POST2)REFERENCES POST(POST1, POST2)
);


데이터 입력하기
===================================================
ALTER TABLE POST DISABLE NOVALIDATE CONSTRAINT PK_POST; //POST 에 제약 일시정지

INSERT INTO POST VALUES('', '', '경기도 성남시 분당구 정자동'); //post 에 데이터 입력

ALTER TABLE POST ENABLE NOVALIDATE CONSTRAINT PK_POST; //POST 에 제약 재실행


ALTER TABLE MEMBER DISABLE NOVALIDATE CONSTRAINT MEMBER_FK_POST; //member 에 제약 일시정지

INSERT INTO MEMBER VALUES('1234', '홍길동', '1', '990101',  // member 에 데이터입력
       '1232344', '712-1234', '100', '010', '');

ALTER TABLE MEMBER ENABLE NOVALIDATE CONSTRAINT MEMBER_FK_POST; // member 에 제약 재실행


출력
====================================================

        ID NAME       S JUMIN1 JUMIN2  TEL             POS POS
---------- ---------- - ------ ------- --------------- --- ---
ADDR
------------------------------------------------------------
      1234 홍길동     1 990101 1232344 712-1234        100 010


====================================================

151008 - integrity / KEY / view / procedure

Data integrity
-----------------

1. What?
(1) 실체 무결성 ( Entity Integrity)
1) 중복을 막음
2) PRIMARY KEY, UNIQUE
(2) 영역 무결성 ( Domain )
1) 범위
2) CHECK
(3) 참조 무결성 ( Reference)
1) 참조
2) FOREIGN KEY (외부에서 온 키)
2. 컬럼(필드) 의 특성
1) NN 속성
2) ND 속성
3) NC 속성
===============================================================================

Primary key 
1) 하나의 테이블에서 단 한개만 사용 가능
2) 여러개의 필드에 설정 가능


------------------------------------------------------
DROP TABLE tbltest;

CREATE TABLE tbltest(
id number null,
name varchar2(10) null
):
중복된 데이터 입력  alter insert create delete drop

INSERT INTO tbltest VALUE (1, '홍길동');
INSERT INTO tbltest VALUE (1, '홍길동');

DELETE FROM tbltest;

ALTER TABLE tbltest ;


** DD(Data Dictionary)
desc user_constraints;
select constraint_name, table_name, status from user_constraints;

desc user_objects;
select object_name from user_objects;

기본키 제약 제거
alter table tbltest drop constraint pk_id;

alter table tbltest add age number null;   //컬럼은 테이블의 구성이기 때문에 생략이 가능하다.
alter table tbltest modify name varchar2(20);

속성 제거
alter table tbltest drop column age;


다시 기본키 장착(두개의 필드를 묶어서 부여)
alter table tbltest add constraint pk_id_name primary key(id, name);
insert into tbltest values (1, '홍길동');
insert into tbltest values (1, '임꺽정');
insert into tbltest values (2, '홍길동');
insert into tbltest values (1. '임꺽정');

drop table tbltest;

select tname from tab;

show recyclebin;

flashback table tbltest to before drop;

purge recyclebin; // 휴지통 비우기

create table tbltest(
id  number primary key,
name varchar2(10) null
);

select constraint_name, table_name, status from user_constraints;

create table tbltest(
id number  constraint pk_id primary key,
name varchar2(10) null
);

create table tbltest(
id number,
name varchar2(10),
constraint pk_id_name primary key(id. name)
);

create table tbltest(
id number,
name varchar2(10) null,
constraint pk_id_name primary key(id)
);

NN속성 확인
INSERT INTO tbltest values(null, '홍길동');
INSERT INTO tbltest(name) values('홍길동');



2. UNIQUE
(1) 하나의 테이블에 여러 개를 설정 가능하다

DROP table tbltest;

create table tbltest(
id number(2) constraint uk_id UNIQUE,
name varchar2(10) constraint uk_name UNIQUE,
age number(2, 3),
gender char(1)
);

// 유니크는 기본키설정 여러개 가능하다.

insert into tbltest(id, name) values(1, '홍길동');
insert into tbltest(id, name) values(1, '임꺽정');
insert into tbltest(id, name) values(2, '홍길동');
insert into tbltest(id) values(2);
insert into tbltest(name) values('신돌석');



3. 중복을 지켜주는 도구 : SEQUENCE, sequence (자동 증가)
drop table tbltest;

create table tbltest(
id number(2),
name varchar2(10)
);

create sequence seq_id;

insert into tbltest values(seq_id.nextval, '홍길동');
insert into tbltest values(seq_id.nextval, '홍길동');
insert into tbltest values(seq_id.nextval, '홍길동');
insert into tbltest values(seq_id.nextval, '홍길동');



4. NULL 값을 지켜주는 도구 : DEFAULT

DROP TABLE tbltest;

CREATE TABLE tbltest(
id number(2)
name varchar2(10) default '무명씨'
age number default(0)
);
insert into tbltest(id) values ( seq_id . nextVal);



5. CHECK
DROP TABLE tbltest;

CREATE TABLE tbltest(
id number(2),
name varchar2(10),
age number,
city varchar2(10),
CONSTRAINT ck_city
CHECK ( city = '서울' or city ='경기' or city = '인천')
);
insert into tbltest values ( seq_id.nextval, '홍길동', 20, '서울');
insert into tbltest values ( seq_id.nextval, '임꺽정', 20, '제주');

ALTER 를 이용해서 age 에 나이를 10~60 세 까지만 입력받을 수 있도록 수정하라

ALTER TABLE tbltest ADD constraint ck_age check ( age between 10 and 60);
6. FOREIGN KEY

CREATE TABLE tblDept(
deptno char(4),
dname varchar2(10),
);
CREATE TABLE tblEmp(
empno number,
ename varchar2(10),
hiredate date,
deptno char(4)
);
insert into tbldept values('1110', '영업부');
insert into tbldept values('1111', '마케팅부');


insert into tblemp values (1, '홍길동', sysdate, '1111');

tlbDept 테이블의 deptno에 기본키 추가
ALTER TABLE tbldept ADD CONSTRAINT pk_deptno PRIMARY KEY ( deptno );

ALTER TABLE tblEmp
ADD CONSTRAINT fk_tbldept_tblemp_deptno FOREIGN KEY (deptno)
REFERENCES tbldept(deptno);
insert into tblemp values ( 2, '임꺽정', sysdate,  '1113);

NN속성
UPDATE tbldept SET deptno = '1100' WHERE deptno='1110';

UPDATE tbldept SET deptno = '2222' WHERE deptno='1111';

참조가 있던 없던 강제로 진행할 때 - CASCADE

=======================================================================

***** VIEW 테이블
1. 가상테이블
2. 실제테이블 을 가지고 여러 관점에서 다양하게 사용할 수 있게 하는 개념
3. 장점 
1) 사용자에게 필요한 필드만 제공
2) 보안성
4. 스키마 수정불가
5. 문법

CREATE [OR REPLACE] VIEW 이름 [{컬럼명...}]
AS SELECT 구문

6. 주의할점 - 조회만 한다면 문제없음
1) View 를 통해 입력되지 않은 컬럼에 대한 수정



*실습
------------
conn system/1111
GRANT create view TO scott;

CREATE OR REPLACE VIEW vw_emp_20
AS
SELECT empno, ename, deptno, job, sal from emp where deptno = 20;

select * from vw_emp_20;

insert into vw_emp_20(empno, ename) values(100,'test');

select object_name from user_objects;

-------------------------------------

CREATE OR REPLACE VIEW vw_emp_20
AS
SELECT ename, deptno from emp where deptno = 20;

insert into vw_emp_20 values('test1',30);
-----------------------------------------

CREATE OR REPLACE VIEW vw_emp_20
AS
SELECT ename, deptno, sal + nvl(comm,0) as total from emp where deptno = 20;

select * from vw_emp_20;
-------------------------------------------

CREATE OR REPLACE VIEW vw_emp_20
AS
SELECT ename, sal emp.deptno, dname, loc from emp 
inner join dept on emp.deptno = dept.deptno and dept.deptno=20;

select * from vw_emp_20

UPDATE vw_emp_20
set sal = 100, loc = 'BOSTTON'
where ename = 'SMITH';

drop view vw_emp_20;
delete from emp where ename='test';

==============================================

*** Stored Procedure
1. 절차적인 구조
[DECLARE
선언부]
BEGIN
코드작성 ( 처리)
[EXCEPTION
예외처리]
END;

2. 문법
CREATE [OR REPLACE] PROCEDURE 이름 [(파라미터 , ...)]
IS
BEGIN
내용
END;
------------------------------------------------
**실습

1. 사번이 7788 인 사원의 급여를 3500 으로 수정하는 프로시저

CREATE OR REPLACE PROCEDURE sp_emp_sal
IS
BEGIN
UPDATE emp
SET sal = 3500
WHERE empno = 7788;
END;
/  -  프로시저 생성시에는 반드시 끝에 슬래쉬를 붙여준다

exec sp_emp_sal // execute pl/xql 처리가 완료되도록 해줌
show error; // 에러를 구체적으로 보여줌
exec sp_emp_sal(3000,7788)
//parameter p //() 매개변수

2. 1번예제를 개선하여 매개변수를 사용할 수 있도록 해보자.

CREATE OR REPLACE PROCEDURE sp_emp_sal
(p_sal in number, p_empno in number)
//(p_sal in emp.sal%type, p_empno in emp.empno%type) 해당 변수와 같은타입으로 써라
IS
BEGIN
UPDATE emp
SET sal = p_sal
WHERE empno = p_empno;
( if 조건식 then // 만약 if조건식이 참이라면
 else 
 end if;)

 if sql%notfound then
 else
 end if;
 
 END;
/
CREATE OR REPLACE PROCEDURE sp_emp_sal
(p_sal in emp.sal%type, p_empno in emp.empno%type)
IS
BEGIN
UPDATE emp
SET sal = p_sal
WHERE empno = p_empno;
 if sql%notfound then
dbms_output,put_line(p_empno|| ' 는  없는 사번임');
 else
dbms_output,put_line(sql%rowcount|| ' 명이 처리됨');
 end if;
END;
/
set serveroutput on 


exec sp_emp_sal(3500,7788);
//pl/sql 처리가완료되었습니다.
set serveroutput on 
exec sp_emp_sal(3500,7788);
//1명이 처리됨
4. 값을 리턴하는 경우
세금계산 프로시저 작성
특정한 수에 7% 의 세금을 계산하여 그 결과를 돌려주는 프로시저

CREATE OR REPLACE PROCEDURE usp_tax
(p_num in number,p_result out number) 
// in 외부로부터 값을 받기위한 , out 외부로 값을 보내기위한
IS
BEGIN
p_result :=p_num * 0.07;
END;
/


var g_result number;
exec usp_tax(3500, :g_result);  // p_num = 3500, p_result = g_result
print : g_result


5. 사원 등록 프로시저
사원의 이름, 업무, 직속상사, 급여 를 입력받는다.
부서번호는 직속상사의 부서번호와 같다.
커미션은 SALESMAN 일 경우 0, 그외에는 null 로 처리

CREATE OR REPLACE PROCEDURE usp_emp_insert
(p_ename in emp.ename%type.p_job in emp.job%type,
p_mgr in emp.ngr%type,p_sal in emp.sal%type) 
IS
v_deptno emp. deptno%type;
v_comm emp. comm%type;
BEGIN
select deptno into v_deptno from emp where empno = p_mgr;
 if then
p_job = 'SALESMAN' than
v_comm:= 0;
 else
v_comm:= null;
 end if;
insert into emp(ename, ename, job, mgr,
sal, deptno, comm, hiredate)
values (seq_empno.nextval, p_ename, p_job, p_mgr, p_sal, 
v_deptno, v_comm, sysdate)
END;
/

exec usp_emp_insert('test1', 'SALESMAN', 7788, 1500);