Flaming Soccer ball
SQL

40일차 22.11.16

leo lee 2022. 11. 16.
반응형

**제약조건
- 컬럼에 대한 조건
- 테이블의 삭제도 방지할 수 있음

*primary key 
-> 중복 허용 안됨
-> null값이 들어가지 않음
-> 가장 강한 제약 조건

*foreign key
-> 중복허용
-> null값 허용
-> pk에 없는 값은 들어갈 수 없음

*not null
-> null값을 허용하지 않음을 지정
-> primary key는 기본적으로 not null

*unique key
-> 데이터가 중복으로 들어갈 수 없음을 지정
-> ex) 주민번호
-> null값 허용

---> not null + unique key = primary key의 성질

*check
-> 특정 컬럼에 값이 들어갈 때 지정된 값만 들어갈 수 있게 지정
-> check() 로 조건 정의

 

 


*제약조건 정의
- 제약조건 이름은 생략 가능하다 -> 생략하게 되면 제약 조건 이름이 자동 생성
- 레퍼런스 -> 테이블의 어떤 컬럼을 참조한다는 것을 명시함
   ex) departments(department_id) 

- default : 값을 지정하지 않았을 때 자동으로 지정해주는 값

-- 테이블끼리 연결시 pk 와 fk 가 연결될 때 같은 데이터타입으로 해주는게 좋음


**제약조건 -> 추가, 삭제는 가능하나 수정은 불가능
- 제약조건의 추가는 add절 이용
- not null 조건은 modify 절을 사용해서 추가 가능



-----------------------------테이블의 생성과 제약조건-------------------------------
--primary key (테이블의 고유 키, 중복X, null허용X)
--unique (중복X)
--not null (null은 허용하지 않음)
--foreign key (참조하는 테이블의 pk를 저장하는 컬럼, 참조테이블의 pk에 없다면 등록X, null허용)
--check (정의된 형식만 저장되도록 허용)
--------------------------------------------------------------------------------

select * from user_constraints;
create table dept2(
    dept_no number(2)      constraint dept2_no_pk primary key,
    dept_name varchar2(15) constraint dept2_name_nn not null, 
    loca number(4)         constraint dept2_loca_locaid_fk references locations(location_id),--foreign key
    dept_date date         default sysdate, --내가 값을 지정하지 않았을 때 기본으로 지정되는 값
    dept_bonus number(10)  default 0, 
    dept_phone varchar2(20)constraint dept2_phone_uk unique,
    dept_gender char(1)    constraint dept2_gender_ck check(dept_gender in ('M', 'F'))
);

desc locations;

--열레벨 제약(constraints 생략가능)
drop table dept2;

create table dept2(
    dept_no number(2)      primary key,
    dept_name varchar2(15) not null, 
    loca number(4)         references locations(location_id),--foreign key
    dept_date date         default sysdate, --내가 값을 지정하지 않았을 때 기본으로 지정되는 값
    dept_bonus number(10)  default 0, 
    dept_phone varchar2(20)unique,
    dept_gender char(1)    check(dept_gender in ('M', 'F'))
);

--테이블 레벨(not null만 열레벨 사용)
create table dept2(
    dept_no number(2),      
    dept_name varchar2(15) not null, 
    loca number(4) ,         
    dept_date date default sysdate, --내가 값을 지정하지 않았을 때 기본으로 지정되는 값       
    dept_bonus number(10) default 0, 
    dept_phone varchar2(20),
    dept_gender char(1),    
    
    constraint dept2_no_pk primary key (dept_no/*,dept_name*/),--슈퍼키
    constraint dept2_loca_locaid_fk foreign key(loca) references locations(location_id),--foreign key
    constraint dept2_phone_uk unique (dept_phone),
    constraint dept2_gender_ck check(dept_gender in ('M', 'F'))
);


--제약조건의 위배
desc employees;

--개체 무결성 위배(null, 중복 pk에 들어가지못함)
insert into employees(employee_id, last_name, email, hire_date, job_id)
values(100, 'test', 'test', sysdate, 'test');

--참조 무결성 위배(참조테이블의 pk로 존재해야 fk로 들어갈 수 있음)
insert into employees(employee_id, last_name, email, hire_date, job_id, department_id)
values(501, 'test', 'test', sysdate, 'test',5);

--도메인 무결성 위배(컬럼에 정의된 값만 들어갈 수 있음)
insert into employees(employee_id, last_name, email, hire_date, job_id, salary)
values(501, 'test', 'test', sysdate, 'test',-10);

--------------------------------------------------------------------------------
--제약조건 추가, 삭제(변경 불가)
drop table dept2;
create table dept2(
    dept_no number(2)      ,
    dept_name varchar2(15) , 
    loca number(4)         ,
    dept_date date         default sysdate, 
    dept_bonus number(10)  default 0, 
    dept_phone varchar2(20),
    dept_gender char(1)   
);
--pk추가
alter table dept2 add constraints dept_no_pk primary key(dept_no);
--fk 추가
alter table dept2 add constraints dept_loca_fk foreign key(loca) references locations(location_id);
--unique추가
alter table dept2 add constraints dept_phone_uk unique(dept_phone);
--check 추가 -dept_gender
alter table dept2 add constraints dept_gender_ck check(dept_gender in ('M', 'F'));
--not null -컬럼 변경문으로
alter table dept2 modify dept_name varchar2(15) not null;

--제약조건 삭제(제약조건명)
alter table dept2 drop constraints dept_loca_fk;


--문제 1
create table members(
    m_name varchar2(20) constraint test1_name_nn not null,
     m_num number(5)     constraint mem_memnum_pk primary key,
    reg_date date       constraint mem_regdate_uk unique not null ,
    gender char(1)      constraint mem_gender_ck check(gender in ('M', 'F')),
    loca number         constraint mem_number_fk 
                        references locations(location_id)
);

desc members;
insert into members values('AAA', 1, '2018-07-01', 'M', 1800);
insert into members values('BBB', 2, '2018-07-02', 'F', 1900);
insert into members values('CCC', 3, '2018-07-03', 'M', 2000);
insert into members values('DDD', 4, sysdate, 'M', 2000);

select * from members order by m_num;


--문제 2
select m_name, m_num, street_address, l.location_id from members m join locations l
on m.loca = l.location_id
order by m_num;

***뷰***
- 개념 잘 알아두기
- 테이블 또는 다른 뷰를 기초로 하는 논리적 테이블 -> 실제로는 존재하지 않는 가상의 테이블
- 조회를 간단하게 하도록 해줌
- 원하는 데이터를 선택, 가짜테이블을 만든 것
*단순 뷰 : 한 개의 원본테이블 사용해서 생성
*복합 뷰 : 조인을 통해 생성된 테이블에 의해 생성

*뷰를 이용한 DML 연산
- 조건이 까다롭

 

/*
뷰는 제한적인 자료만 보기 위해 사용할 수 있는 가상테이블의 개념이다
뷰는 기본테이블로 유도된 가상테이블이기 때문에 필요한 컬럼만 저장해두면 관리가 용이해진다
뷰는 가상테이블로 실제 데이터가 물리적으로 저장된 형태는 아니다
뷰를 통해서 데이터에 접근하면 원본데이터는 안전하게 보호할 수 있다.
*/

select * from emp_details_view;

--단순뷰
--뷰의 컬럼 이름은 함수같은 가상 표현식이면 안됨
create or replace view view_emp
as(select employee_id,
          first_name || ' ' || last_name as name,
          job_id,
          salary
    from employees
    where department_id = 60
    );
    
--복합 뷰
--여러 테이블을 조인하여 필요한 데이터만 저장하고 빠른 확인을 위해서 사용
create or replace view view_emp_dept_job
as(select e.employee_id,
             first_name || ' ' || last_name as name,
             d.department_name,
             e.salary,
             j.job_title
    from employees e
    left outer join departments d
    on e.department_id = d.department_id
    left outer join jobs j
    on e.job_id = j.job_id)
    order by employee_id;
    
select * from view_emp_dept_job;
   

--뷰의 수정(동일이름으로 만들면 수정된다)
create or replace view view_emp_dept_job
as (select
        e.employee_id,
        first_name || ' ' || last_name as name,
        e.salary, -- 추가
        d.department_id,
        j.job_title
     from employees e
     left outer join departments d
     on e.department_id = d.department_id
     left outer join jobs j
     on e.job_id = j.job_id)
     order by employee_id;   
    
    
select * from view_emp_dept_job;
--뷰를 이용하면 데이터를 손쉽게 조회 가능
--job_title별 salary 평균
select j.job_title,avg(e.salary)as 평균 from jobs j left join employees e on j.job_id = e.job_id group by job_title order by 평균;

select job_title, avg(salary) as 평균 from(select * from employees e left join jobs j on e.job_id = j.job_id)
group by job_title
order by 평균;

--뷰를 통한 조회
select job_title, avg(salary) as 평균
from view_emp_dept_job
group by job_title
order by 평균;

--뷰의 삭제
drop view 뷰이름;

--------------------------------------------------------------------------------
--뷰를 통한 DML은 제한이 많음
--가상열 컬럼이 있다면 허용되지 않음
insert into view_emp_dept_job(name, employee_id) values('xxx',300);
--원본 테이블의 null을 허용하지 않는 경우도 안됨
insert into view_emp_dept_job(employee_id, salary) values(300, 10000);
-- join된 뷰의 경우도 허용되지 않음
insert into view_emp_dept_job(employee_id, job_title) values(300, 'xxx');

--------------------------------------------------------------------------------
--뷰의 옵션
--with check option -조건 컬럼 제약
create or replace view view_emp_test
as(select employee_id, first_name, department_id
from employees where department_id in (60,70,80))
with check option;

select * from view_emp_test;

--with read only-읽기 전용뷰(조회만 가능)
create or replace view view_emp_test
as(select employee_id, first_name, department_id
from employees where department_id in (60,70,80))
with read only;

select * from view_emp_test;

 

 


*******************************시퀀스*******************************
- 기본 키 값을 생성하기 위해 사용
- maxvalue : 시퀀스의 최대값
- minvalue : 시퀀스의 최소값

- currval : 현재 시퀀스 값 조회*********************************
-> nextval로 하나의 값이 들어간 상태에서 사용 가능

- nextval : 다음 시퀀스 값 조회*********************************

--시퀀스(순차적으로 증가하는 값 - pk에 많이 사용된다)
select * from user_sequences;


--테이블 
create table dept3 (
    dept_no number(2) primary key,
    dept_name varchar2(20),
    loca varchar2(20),
    dept_date date
); 

--시퀀스 생성
create sequence dept3_seq
    increment by 1
    start with 1
    maxvalue 10
    minvalue 1
    nocycle
    nocache;
--시퀀스 삭제
drop sequence dept3_seq; 

--시퀀스 사용 currval, nextval
select dept3_seq.currval from dual; --currval는 nextval최소 한번 이후에 사용가능
select dept3_seq.nextval from dual;

insert into dept3(dept_no, dept_name, loca, dept_date)
values(Dept3_seq.nextval, 'test', 'test', sysdate);

select * from dept3;

--시퀀스 수정
alter sequence dept3_seq nocache;
alter sequence dept3_seq maxvalue 1000;
alter sequence dept3_seq increment by 1;

--시퀀스가 테이블에서 사용되고 있다면 drop불가 
--시퀀스 값을 초기화 하려면
--1. 현재시퀀스 확인
select dept3_seq.currval from dual;
--2. 증가값을 -현재 시퀀스
alter sequence dept3_seq minvalue 0;
alter sequence dept3_seq increment by -14;
--3. nextval로 실행
select dept3_seq.nextval from dual;
--4. 증가값을 1로 변경 
alter sequence dept3_seq increment by 1;
--5. 실행
select dept3_seq.nextval from dual;

--------------------------------------------------------------------------------
--시퀀스 사용의 응용--

create table dept4(
    dept_no varchar2(30) primary key,
    dept_name varchar2(30)
);
drop table dept4;
drop sequence dept4_seq;
create sequence dept4_seq nocache;
--lpad('값', '맥스길이', '채울값')를 이용해서 pk에 적용하는 값을 (년-0000시퀀스) 형태로 insert

insert into dept4 values(to_char(sysdate, 'YYYY')|| '-'|| lpad(dept4_seq.nextval,5,'0'),'test');
select * from dept4;
select to_char(sysdate, 'YYYY') from dual;
반응형

'SQL' 카테고리의 다른 글

42일차 22.11.18  (0) 2022.11.18
41일차 22.11.17  (0) 2022.11.17
39일차 22.11.15  (0) 2022.11.15
38일차 22.11.14  (0) 2022.11.15
37일차 22.11.11  (0) 2022.11.11

댓글